86

What is the best way to return an image with 2 parameters (x and y for resize).

For example

~/api/image12345/200/200

Will return a 200 by 200 jpg/png/or gif

Should I return a System.Drawing.Image object or manually define the HTTPReponseMessage.Content?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Max Alexander
  • 5,471
  • 6
  • 38
  • 52

2 Answers2

152

You shouldn't return a System.Drawing.Image, unless you also add a formatter which knows how to convert that into the appropriate bytes doesn't serialize itself as the image bytes as you'd expect.

One possible solution is to return an HttpResponseMessage with the image stored in its content (as shown below). Remember that if you want the URL you showed in the question, you'd need a route that maps the {imageName}, {width} and {height} parameters.

public HttpResponseMessage Get(string imageName, int width, int height)
{
    Image img = GetImage(imageName, width, height);
    using(MemoryStream ms = new MemoryStream())
    {
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        result.Content = new ByteArrayContent(ms.ToArray());
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");

        return result;
    }
}

But again, if you are doing this in many places, going the formatter route may be the "recommended" way. As almost everything in programming, the answer will depend on your scenario.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
  • Should the image be in a using too? – dibs487 Jan 30 '17 at 15:35
  • Where is `GetImage` method? – Yoda Apr 26 '18 at 13:44
  • 1
    @Yoda it's the method on your implementation that would return the image that needs to be transferred back to the client. – carlosfigueira Apr 26 '18 at 16:01
  • If you are returning a file from the hard drive, I think it would be better performance to use a FileStream, like this (see accepted answer in this question): https://stackoverflow.com/questions/11125535/how-to-return-a-file-using-web-api – John Gilmer Apr 26 '20 at 00:42
20

Images are heavy. ASP.NET WebForms, HttpHandlers, MVC, and Web API all do a absolutely terrible job of serving static files. IIS does an extremely good job of that - Often 20-100x more efficiently.

If you want to get good performance, do URL rewriting at the latest during PostAuthorizeRequest, so IIS can pick up and serve the file. Yes, this means HttpModule-level event handling.

[Disclaimer: I'm the author of the following article and open-source project]

If you're doing something dynamic with images, check out this article on image processing pitfalls to avoid, and consider taking a look at ImageResizer. It has excellent disk caching (which uses IIS static file handling), and is easy to connect to image generation of any kind. It has optional bindings for AForge, FreeImage, and WIC as well, if you need to get advanced.

Lilith River
  • 16,204
  • 2
  • 44
  • 76
  • 2
    I have been using ImageResizer in my project and am very happy with how it works - plus from me. Only gripe is some of the documentation needs updating. – Jon L Sep 03 '17 at 10:16