Can an ASP.NET MVC controller return an Image? Can an ASP.NET MVC controller return an Image? asp.net asp.net

Can an ASP.NET MVC controller return an Image?


Use the base controllers File method.

public ActionResult Image(string id){    var dir = Server.MapPath("/Images");    var path = Path.Combine(dir, id + ".jpg"); //validate the path for security or use other means to generate the path.    return base.File(path, "image/jpeg");}

As a note, this seems to be fairly efficient. I did a test where I requested the image through the controller (http://localhost/MyController/Image/MyImage) and through the direct URL (http://localhost/Images/MyImage.jpg) and the results were:

  • MVC: 7.6 milliseconds per photo
  • Direct: 6.7 milliseconds per photo

Note: this is the average time of a request. The average was calculated by making thousands of requests on the local machine, so the totals should not include network latency or bandwidth issues.


Using the release version of MVC, here is what I do:

[AcceptVerbs(HttpVerbs.Get)][OutputCache(CacheProfile = "CustomerImages")]public FileResult Show(int customerId, string imageName){    var path = string.Concat(ConfigData.ImagesDirectory, customerId, "\\", imageName);    return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");}

I obviously have some application specific stuff in here regarding the path construction, but the returning of the FileStreamResult is nice and simple.

I did some performance testing in regards to this action against your everyday call to the image (bypassing the controller) and the difference between the averages was only about 3 milliseconds (controller avg was 68ms, non-controller was 65ms).

I had tried some of the other methods mentioned in answers here and the performance hit was much more dramatic... several of the solutions responses were as much as 6x the non-controller (other controllers avg 340ms, non-controller 65ms).


To expland on Dyland's response slightly:

Three classes implement the FileResult class:

System.Web.Mvc.FileResult      System.Web.Mvc.FileContentResult      System.Web.Mvc.FilePathResult      System.Web.Mvc.FileStreamResult

They're all fairly self explanatory:

  • For file path downloads where the file exists on disk, use FilePathResult - this is the easiest way and avoids you having to use Streams.
  • For byte[] arrays (akin to Response.BinaryWrite), use FileContentResult.
  • For byte[] arrays where you want the file to download (content-disposition: attachment), use FileStreamResult in a similar way to below, but with a MemoryStream and using GetBuffer().
  • For Streams use FileStreamResult. It's called a FileStreamResult but it takes a Stream so I'd guess it works with a MemoryStream.

Below is an example of using the content-disposition technique (not tested):

    [AcceptVerbs(HttpVerbs.Post)]    public ActionResult GetFile()    {        // No need to dispose the stream, MVC does it for you        string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "myimage.png");        FileStream stream = new FileStream(path, FileMode.Open);        FileStreamResult result = new FileStreamResult(stream, "image/png");        result.FileDownloadName = "image.png";        return result;    }