I'm working on a .NET HTTP handler (with IsReusable set to true) to return an image based on a specified ID. The passed URL would look something like this ReadImage.ashx?id=N
. Once the handle receives the request it takes the ID and looks in the HTTP cache for the previously base64 encoded image, like this:
byte[] image;
if (context.Cache["image_" + id] != null)
{
image = Convert.FromBase64String(context.Cache["image_" + id].ToString());
}
If it's not there, it proceeds to get the filename from the database, read the file from disk, encode it to base64 and store the bytes in image
and finally cache the image for 20 minutes like this:
else
{
var dbImage = m_database.Images.Single(i => i.Id.Equals(id));
string filePath = context.Server.MapPath(string.Format("~/{base path}/{0}", dbImage.Filename));
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
image = new byte[fs.Length];
fs.Read(image, 0, image.Length);
context.Cache.Add("image_" + dbImage.Id, Convert.ToBase64String(image), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20), CacheItemPriority.Normal, null);
}
}
Then I finally BinaryWrite
my image
buffer to the output stream of the current context:
context.Response.ContentType = "image/png";
context.Response.BinaryWrite(image);
context.Response.Flush();
Now, this is all working perfectly fine - but not ALL the time. I'll occasionally get a broken image, but upon refresh the image is (99% of the time) there.
Looking at the network traffic in Chrome's debugger I can see that my handler is returning text/html
in cases where the image is broken and not image/png
as it should be. I've tried wrapping my handler in a try-catch
and recording the exception details, but it doesn't do anything - it just continues to return garbage to the requesting page.
So far I've tried a few things:
- Buffering out my
image
in 4096 chunks.
- Creating a
Bitmap
object and returning this.
- Removing the caching completely (it fails slightly more frequently if I do this).
- Trying to capture exceptions and record them (it never throws an exception).
Am I missing the obvious here?? I'm a little stumped, anyone have any advice?