Override Content-Length header with a custom value

832 Views Asked by At

I have a controller returning an image, but the image was cut off at the bottom in the front-end (in the browser), after some digging I found out it's because the Content-Length response header was smaller then the actual file size (by some 500 bytes) so it didn't show the full file. (i.e. it only showed the files content till the Content-Header byte length and not till the actual files byte length, so it didn't read the full file)

(p.s. the Content-Length header was actually the right size but the file get's bigger when sent to the front-end I believe due to some compression happening, but the Content-Length doesn't get updated with the new size and stays with the files original length...)

so my first instinct was to overwrite the Content-Length prop in the controller like this:

HttpContext.Response.ContentLength = result.length + 500;

but it didn't change anything in the response, and for some reason it doesn't overwrite the Content-Length header and it still takes it's value from the files actual files length

so my solution currently is to add 500 empty bytes to the response so the Content-Length is automatically longer :

byte[] byteArr = new byte[Convert.ToInt32(result.Length + 500)];
result.CopyTo(byteArr, 0);
return byteArr;

but this solution seems wrong and messy, so can someone please tell me

  1. why is the Content-Length off
  2. why can't I overwrite the Content-Length header
  3. and how to properly overwrite it (or make the Content-Length right)

this is my controller code

[Route("get-my-images")]
public async Task<ActionResult> GetMyImages(int id, Guid logged)
{
   var user = await _context.Users.FindAsync(id);
   if (user != null && (user.LoggonToken == logged || user.LinkToken == logged))
   {
      Images image = _context.Images.FirstOrDefault();
      if (image == null) return StatusCode(404, new { Message = "Image Not Found" });

      HttpContext.Response.Headers.Add("systemn-name", image.SystemName.ToString());
      HttpContext.Response.Headers.Add("display-name", image.DisplayName);
      HttpContext.Response.Headers.Add("created-at", image.CreatedAt.Humanize(true));
      HttpContext.Response.Headers.Add("created-day", $"{image.CreatedAt.DayOfWeek}");
      HttpContext.Response.Headers.Add("flagged-level", image.FlaggedLevel.ToString());
      HttpContext.Response.Headers.Add("size", image.Size.Bytes().Humanize());
      HttpContext.Response.Headers.Add("format", image.Format.ToUpper());
      HttpContext.Response.Headers.Add("image-id", image.Id.ToString());
      HttpContext.Response.Headers.Add("image-number", image.ImageNumber.ToString());
      HttpContext.Response.Headers.Add("device", image.Device.DeviceName);

      byte[] result = GetImageFromHardDrive(image);

      // doesn't work
      // HttpContext.Response.ContentLength = result.Length + 500;

      // current solution...
      // byte[] byteArr = new byte[Convert.ToInt32(result.Length + 500)];
      // result.CopyTo(byteArr, 0);
      // return base.File(byteArr, "image/jpeg");
      return base.File(result, "image/jpeg");
   }
   return StatusCode(401, new { Message = "User Not Found" });
}
1

There are 1 best solutions below

0
On

I haven't found a clean solution yet, but what I did find is that it only happens to JPEG images, so I started saving the images as WebP images instead of Jpeg (using ImageProcessor library) and that solved the problem, the images are bigger in size but I'll have to deal with that...