3

I've been spinning my tires trying to use ASP.NET Web API to return images. I've seen a number of examples, but I keep running into problems.

After searching for a solution, most examples suggest using HttpResponseMessage and setting the Content and Content-Type header correctly. For example in the following posts: WebApi: How to handle Images ASP .Net Web API downloading images as binary

Here's what I am doing now:

    [System.Web.Http.HttpGet]
    [ActionName("ConvertHTMLToImage")]
    public HttpResponseMessage ConvertHTMLToImage(string htmlString)
    {
        var path = @"C:\temp\mona-lisa.png";
        var response = Request.CreateResponse(HttpStatusCode.OK);
        var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
        response.Content = new StreamContent(fileStream);
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
        return response;
    }

I'm getting mixed results. When I go the URL for that resource I have problems with Chrome (This webpage is not available), Firefox (The connection was reset), and Safari (Safari can’t open the page). Much to my surprise, it works fine in IE. I can also successfully view the image using the composer in Fiddler. If I keep Fiddler open and access the resource using Chrome/Firefox/Safari, I see 504 errors. Not sure what the means, I can't remember ever having seen that error type before.

I also noticed some strange behavior in the debugger with the browsers that aren't working. If I call ConvertHTMLToImage from IE and Fiddler, I see it stop at my break-point once and then the image is sucessfully returned to the client. On Chrome/Firefox/Safari there are multiple calls into the method. Sometimes twice sometimes 3 times. I have no explanation for this. I don't get any errors that I can detect other than the browser doesn't show the image.

I've done this same thing using aspx pages, HttpHhandlers, and other .NET methods so I know there are work-arounds, but I really would like to know what I'm doing wrong. This seems like something that should be easily accomplished using the Web API.

Community
  • 1
  • 1
cwineman
  • 31
  • 1
  • 1
  • 2
  • 1
    Maybe try reading your file into a `byte[] buffer` array from the `FileStream` first, then close the file stream and open a `MemoryStream` with the contents of the buffer and then pass this to the response stream. – Lukasz M Feb 05 '14 at 19:05
  • I tried that and other variations, but had the same problem. It does seem to be related to a stream not being terminated, though. I've seen several posts talking about how HttpResponseMessage is supposed to be closed/disposed by the underlying infrastructure, but I haven't found any documentation about it. Wish I could find some. – cwineman Feb 05 '14 at 19:34
  • I've made a sample test project and it seems to display images correctly (except that IE wants to download the image instead of displaying it). To make sure if it's related with streams, try to read the file to a `byte[]` buffer and use `ByteArrayContent` as described here: http://stackoverflow.com/a/12468615/232530. – Lukasz M Feb 05 '14 at 19:49
  • Hmmm. I tried nearly the exact same thing. The only difference is that I used Image img = Image.FromFile(path); instead of Image img = GetImage(imageName, width, height); I still have the same issues. What the hell is causing the multiple requests, I wonder. – cwineman Feb 05 '14 at 21:12
  • By any chance, did you figure out the cause of this issue? I'm having the same one, and have already spent hours trying to resolve it. – Shan Plourde May 16 '14 at 21:16

3 Answers3

5

This solved the issue for me WebApi: How to handle Images

In short

[System.Web.Http.HttpGet]
[ActionName("ConvertHTMLToImage")]
public HttpResponseMessage ConvertHTMLToImage()
{  
     string filePath = @"C:\temp\mona-lisa.png";

     var result = new HttpResponseMessage(HttpStatusCode.OK);

     FileStream fileStream = new FileStream(filePath, FileMode.Open);
     Image image = Image.FromStream(fileStream);
     MemoryStream memoryStream = new MemoryStream();
     image.Save(memoryStream, ImageFormat.Jpeg);

     result.Content = new ByteArrayContent(memoryStream.ToArray());
     result.Content.Headers.ContentType = new  MediaTypeHeaderValue("image/jpeg");
     return result;
}
Community
  • 1
  • 1
Pablo Retyk
  • 5,690
  • 6
  • 44
  • 59
0

I used this recently in my project:

public HttpResponseMessage Get(int IRN)
        {
            try
            {
                Multimedia image = new Multimedia();
                MemoryStream imageStream = image.GetMedia(IRN);
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
                response.Content = new StreamContent(imageStream);
                response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
                return response;
            }
            catch (Exception ex)
            {
                return HandleError(ex);           
            }

        }

GetMedia function:

    .....
                MemoryStream mediaStream = new MemoryStream();
    ...
    FileStream temp = resource["file"] as FileStream;
                            mediaStream.SetLength(temp.Length);
                            temp.Read(mediaStream.GetBuffer(), 0, (int)temp.Length);

                            temp.Close();
....

  return mediaStream;

resource["file"] is an array which contained a filestream object.

Hope this helps.

  • That looks essentially like what I am doing. But what happens when you go to the URL for your web method in a browser? I want to be able to just browse to my resource. In IE it works, but not in any other browser. – cwineman Feb 20 '14 at 19:55
0

Try this(replace jpg with png as desired):

var result = new HttpResponseMessage(HttpStatusCode.OK);    
String filePath = HostingEnvironment.MapPath("~/Images/123.jpg");
FileStream fileStream = new FileStream(filePath, FileMode.Open);
Image image = Image.FromStream(fileStream);
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Jpeg);
var byteArrayContent = new ByteArrayContent(memoryStream.ToArray());
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
result.Content = byteArrayContent;
return result;
Syed Waqas
  • 2,576
  • 4
  • 29
  • 36