我正在使用.NET HTTP处理程序(IsReusable设置为true)来返回基于指定ID的图像。传递的URL看起来像这个ReadImage.ashx?id=N
。一旦句柄收到请求,它就会获取ID并在HTTP缓存中查找以前的base64编码图像,如下所示:
byte[] image;
if (context.Cache["image_" + id] != null)
{
image = Convert.FromBase64String(context.Cache["image_" + id].ToString());
}
如果它不存在,它继续从数据库中获取文件名,从磁盘读取文件,将其编码为base64并将字节存储在image
中,最后将图像缓存20分钟,如下所示: / p>
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);
}
}
然后我终于BinaryWrite
我的image
缓冲区到当前上下文的输出流:
context.Response.ContentType = "image/png";
context.Response.BinaryWrite(image);
context.Response.Flush();
现在,这一切都很好 - 但并不是所有时间。我偶尔会得到一张破损的图像,但刷新图像的时间是(99%的时间)。
查看Chrome调试器中的网络流量,我可以看到我的处理程序在图像被破坏而不是text/html
的情况下返回image/png
。我已经尝试将我的处理程序包装在try-catch
中并记录异常详细信息,但它没有做任何事情 - 它只是继续将垃圾返回到请求页面。
到目前为止,我尝试了一些事情:
image
。Bitmap
对象并将其返回。我错过了这里显而易见的事吗?我有点难过,有人有什么建议吗?
答案 0 :(得分:1)
我的猜测。我的问题在于以下代码:
if (context.Cache["image_" + id] != null)
{
image = Convert.FromBase64String(context.Cache["image_" + id].ToString());
}
缓存可能在任何时间变为无效。很有可能在if语句求值为true之后,缓存项立即变为无效,最终第二次获取将变为null。最好这样做(不是100%肯定):
var base64String = context.Cache["image_" + id].ToString();
if (base64String != null) image = ...
答案 1 :(得分:0)
不是解决方案,而是更好的解决方法。
我决定为它创建一个MVC动作,而不是使用通用处理程序。这是行动,我没有一次失败,而且似乎要快得多。
[HttpGet]
public ActionResult GetImage(int id)
{
byte[] buffer;
if (HttpContext.Cache["image_" + id] == null)
{
var dbMediaItem = m_database.MediaItems.Single(i => i.Id.Equals(id));
string path = string.Format(Server.MapPath("~/{base path}/{0}"), dbMediaItem.Filename);
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
HttpContext.Cache.Add("image_" + id, Convert.ToBase64String(buffer), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20), CacheItemPriority.Normal, null);
}
}
else
{
buffer = Convert.FromBase64String(HttpContext.Cache["image_" + id].ToString());
}
return base.File(buffer, "image/png");
}