Search code examples
.net-coreasp.net-core-webapimime

.Net Core - Send image through api = Resource interpreted as Document but transferred with MIME type image/jpeg


In the wwwroot folder of my .Net Core MVC application, I have some images. I need to serve these pictures to TopDesk, where I can put in a url which gets embedded. I have no influence on Topdesk. I can only change the way the image is served.

When I use a direct link to the image, it works. The image gets embedded

Example of direct url:

https://my.web.site/images/image001.jpeg

But there is a limited embedded size (600px) so i need to resize the images. For that purpose I wrote a very simple api controller:

[HttpGet]
[Route("api/Images/GetImage/{id}")]
public IActionResult GetImage(string id)
{
    try
    {
      var pad = $"c:\\Images\\{id}";
      if(System.IO.File.Exists(path))
      {
          var fileBytes = System.IO.File.ReadAllBytes(path);
          var smallImage = ..... doing resizing;
          new FileExtensionContentTypeProvider().TryGetContentType(Path.GetFileName(path), out var contentType);
          return File(smallImage , contentType ?? "application/octet-stream", $"{id}");
      }
      return NotFound();
    }
    catch(Exception ex)
    {
        return BadRequest(ex.Message);
    }
}

but the url

https://my.web.site/api/images/GetImage/image001.jpeg

results in

Resource interpreted as Document but transferred with MIME type image/jpeg

The image doesn't show. When i test the url in Postman, it returns the image without warning. What am i missing here?


Solution

  • Instead of returning a File, try using FileContentResult instead:

    [HttpGet]
    [Route("api/Images/GetImage/{id}")]
    public IActionResult GetImage(string id)
    {
      try
      {
        var path = $"c:\\Images\\{id}";
        if(System.IO.File.Exists(path))
        {
          var fileBytes = System.IO.File.ReadAllBytes(path);
          var smallImage = ..... doing resizing;
          new FileExtensionContentTypeProvider().TryGetContentType(Path.GetFileName(path), out var contentType);
          return new FileContentResult(fileBytes, contentType ?? "application/octet-stream");
        }
      return NotFound();
      }
      catch(Exception ex)
      {
        return BadRequest(ex.Message);
      }
    }
    

    When navigating to /GetImage/{id} with a browser, you will see that with File the browser tends to download the file, but with FileContentResult it displays the image in the browser tab directly, which is the same behavior as using static files. This is probably happening because of the Response Headers being added when using File/FileContentResult (probably a Content-Disposition header). Not sure how TopDesk is using these images though.

    Off-topic: It's also a good practice to not instantiate a FileExtensionContentTypeProvider with every request. Instead, you can register it as a singleton in your Startup.cs like:

    services.AddSingleton(new FileExtensionContentTypeProvider());
    

    and inject it in your controller's constructor.