locked
Downloading image data from HttpHandler that serves image RRS feed

  • Question

  • User768014394 posted

    I have an HTTP handler that is used to dynamically generate images and I need to call it from a page and write the result to the HttpOutputStream without opening a new window.

    After a bit of research it seems that using the WebClient makes sense here.  I've tried the following, but I always seem to get corrupt images.  I know the Handler actually works however because if I put an image tag in a web page and set the URL to the handler, I see the image.

    string url = "http://mywebsite.comm/GetImage.ashx?id=1234&width=1024&height=768";
    WebClient webClient = new WebClient();
    byte[] image = webClient.DownloadData(url);
    
    Response.ContentType = "image/jpeg";
    Response.AppendHeader("Content-Disposition", string.Format("attachment; filename={0}", "Test.jpg"));
    Response.AppendHeader("Content-Length", image.Length.ToString());
    Response.BinaryWrite(image);
    Response.End(); 

    What am I doing wrong?

    Friday, February 15, 2013 12:29 PM

Answers

  • User-905528745 posted

    Well this is the wrong way for sure.  If it is the same web application you simply need to export the HTTP handler functionality out to common grounds, like a DLL or if in the same project, a separate class.  And that's it.  The Save As for the image is achieved simply by changing ContentType to "application/force-download" if your content disposition of "attachment" is not working for you.  Note, however that such content type is a hack to trick web browsers.  Use at your own risk.

    So to summarize:  Add a new class to the project (make it static) and call it something like "ImageProvider".  Add a single static method public static byte[] GetImage(string id) and add the image-retrival code in it.  Make sure you return the byte array that composes the image. Now you are free to call ImageProvider.GetImage() anywhere in your code instead of the horrible WebClient approach.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, February 15, 2013 6:51 PM

All replies

  • User-905528745 posted

    How do you determine the received data is corrupt?  How are you converting the byte array?

    Friday, February 15, 2013 12:39 PM
  • User768014394 posted

    I've tried writing the byte array to disk as well as streaming it to the client and the result cannot be opened in an image viewer.

    Friday, February 15, 2013 12:43 PM
  • User768014394 posted

    I opened the file on disk with a text editor and it's HTML from the login page from my application.  Apparently, the request isn't authenticated...How do I get around that without disabling security on my site?

    Friday, February 15, 2013 1:11 PM
  • User768014394 posted

    Never mind, I found this:

    http://msdn.microsoft.com/en-us/library/system.net.webclient.credentials.aspx

    The Credentials property contains the authentication credentials used to access a resource on a host. In most client-side scenarios, you should use the DefaultCredentials, which are the credentials of the currently logged on user. To do this, set the UseDefaultCredentials property to true instead of setting this property.

    If the WebClient class is being used in a middle tier application, such as an ASP.NET application, the DefaultCredentials belong to the account running the ASP page (the server-side credentials). Typically, you would set this property to the credentials of the client on whose behalf the request is made.

    Friday, February 15, 2013 1:14 PM
  • User768014394 posted

    Well, that doesn't work.  I've tried using webClient.UseDefaultCredentials = true and webClient.Credentials = CredentialCache.DefaultCredentials.  The resulting bytes contain the HTML of the login page.

    I added this line before I tried downloading data:

    ICredentials credentials = webClient.Credentials

    The Domain, Password and UserName properties are all set to empty strings.  My site uses FormsAuthentication so I need the user's identity to pass through so I can get my image.

    Friday, February 15, 2013 1:26 PM
  • User-905528745 posted

    Ok, so where is this code with the WebClient object?  Some desktop application trying to consume the images of a web application of yours?

    Friday, February 15, 2013 3:05 PM
  • User768014394 posted

    It's in the same web application.  While we use the handler to display images on some pages, we need to be able to click a button to get a "save-as" dialog to appear so the image can be saved on the client's hard drive.  Right now we open a page with the image on it and the user is required to right-click the image, but they don't like doing that that.  I've used handlers a lot in the past but I've never tried doing it this way.  I'm under a deadline and wanted to go this route instead of rewriting the handler that already exists.

    The handler must serve up the image as opposed to just reading it from disk because we are applying adjustments to brightness, contrast, and resizing on the fly.  That part works fine, I just need to grab the output from the handler and redirect it to the output stream when the download button on my page is clicked.

    Friday, February 15, 2013 3:25 PM
  • User-905528745 posted

    Well this is the wrong way for sure.  If it is the same web application you simply need to export the HTTP handler functionality out to common grounds, like a DLL or if in the same project, a separate class.  And that's it.  The Save As for the image is achieved simply by changing ContentType to "application/force-download" if your content disposition of "attachment" is not working for you.  Note, however that such content type is a hack to trick web browsers.  Use at your own risk.

    So to summarize:  Add a new class to the project (make it static) and call it something like "ImageProvider".  Add a single static method public static byte[] GetImage(string id) and add the image-retrival code in it.  Make sure you return the byte array that composes the image. Now you are free to call ImageProvider.GetImage() anywhere in your code instead of the horrible WebClient approach.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, February 15, 2013 6:51 PM