3

This question is related this one: Cannot render image to HttpContext.Response.OutputStream. It is not a duplicate.

When attempting to save a PNG to the Response.OutputStream I am experiencing inconsistent behavior between the local development environment and the production environment. Namely, the code I was using originally worked fine locally, but failed on the production server.

Here is the original code which worked locally:

using (Bitmap bmp = challenge.RenderImage()) { 
    bmp.Save(context.Response.OutputStream, ImageFormat.Png); 
}

Despite working locally, when I deployed that on the production server I received an Application Error:

A generic error occurred in GDI+.

After some digging I determined that the problem was in the fact that 'Saving a PNG image requires a seekable stream.'- which the Response.OutputStream is not. The problem was easily mitigated by first writing the Bitmap to a System.IO.MemoryStream, and then to the Response.OutputStream.

using (Bitmap bmp = challenge.RenderImage()) {
    using(MemoryStream ms = new MemoryStream()) {
        bmp.Save(ms, ImageFormat.Png);
        ms.WriteTo(context.Response.OutputStream);
    }
}

What I am curious to know is why the original code worked fine locally, but failed on the production server? The reasoning behind the code failing sounds pretty black-and-white to me, so I don't understand why the environment-specific inconsistency could exist at all.

Community
  • 1
  • 1
Nathan Taylor
  • 24,423
  • 19
  • 99
  • 156
  • are you using the same webserver locally and production? im thinking difference between the embedded server in VS or Cassini and IIS. – Pauli Østerø Oct 13 '10 at 02:05
  • @BurningIce This was the first thought that occurred to me too. I only tested the behavior in Cassini locally, while the production environment is running IIS. – Nathan Taylor Oct 13 '10 at 02:06
  • well, it should be pretty easy to find out... put a debug point in your code locally and check with your debugger if context.Response.OutputStream seems to be seekable. – Pauli Østerø Oct 13 '10 at 02:10

1 Answers1

0

Theoretically you can implement your own stream that is seekable and add it as filter on your Response.Filter attribute, so maybe Cassini is doing something like that under the hood. This is an example hooking up your own stream: http://www.ericis.com/2007/6/21/Obtaining%20ResponseOutputStreamLength

Pauli Østerø
  • 6,878
  • 2
  • 31
  • 48