使用 HttpHandler 流式传输数据库图像
Posted
技术标签:
【中文标题】使用 HttpHandler 流式传输数据库图像【英文标题】:Streaming Databased Images Using HttpHandler 【发布时间】:2010-12-03 05:10:25 【问题描述】:很长一段时间以来,当我在本地计算机上处理涉及数据库图像的 Web 应用程序项目时,我注意到一些烦人的事情。本地是指在我的工作站上使用 VS 2008 和 SQL Server 2005 的典型环境。每当我使用 HttpHandler 在本地显示图像时,每个页面加载时只会呈现一些图像。
但是,当我将应用程序推送到托管环境时,问题通常会消失。但是,我刚刚将一个新项目推出到托管环境中,并遇到了与本地相同的问题 - 这次站点和数据库位于托管环境中的同一台服务器上。有人知道这里发生了什么吗?
这是处理程序:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class FeaturedHandler : IHttpHandler
Business biz = new Business();
public void ProcessRequest(HttpContext context)
if (context.Request.QueryString["ListingID"] != null)
int listingID = Convert.ToInt32(context.Request.QueryString["ListingID"]);
DataSet ds = biz.GetFeaturedImageByID(listingID);
DataRow row = ds.Tables[0].Rows[0];
byte[] featureImage = (byte[])row["Photo"];
context.Response.ContentType = "image/jpeg";
context.Response.OutputStream.Write(featureImage, 0, featureImage.Length);
else
throw new ArgumentException("No ListingID parameter specified");
public bool IsReusable
get
return false;
我曾尝试在单独的服务器上使用数据库,但遇到了同样的问题。我应该改用 DataReader 吗?
更新 因为我正在读取二进制数据,所以我最初应该使用 DataReader。
【问题讨论】:
可能相关:***.com/questions/5500950/… 【参考方案1】:我终于通过将 IsReusable 属性的值更改为 true 来渲染所有图像:
public bool IsReusable
get
return true;
显然,这将处理程序保留在内存中并能够处理多个请求。当设置为 false 时,它必须为每个传入请求创建一个新的处理程序实例。
【讨论】:
噢!我不敢相信我们错过了。我总是将“IsReusable”设置为 true。我什至没有在您的代码中查看它。恭喜您找到解决方案。 我真的很想知道在这种情况下将“IsReusable”设置为 true 有什么帮助。新的处理程序不应该总是能够提供图像吗?此处的示例是流式传输动态大小的图像,并将“IsReusable”设置为 false:c-sharpcorner.com/UploadFile/desaijm/… 在 MSDN 上找不到该属性的适当文档,只能通过测试观察...【参考方案2】:通过这个:
每当我使用 HttpHandler 在我的本地显示图像,只有一个 图像的一部分呈现在每个 页面加载。
您的意思是相同的图像出现在应该出现不同图像的地方,还是有些图像出现而有些根本不显示?
在您的情况下,将 isReusable
切换为 true 的区别在于,new Business();
将为多个图像调用一次。如果 isReusable
为 false,则每个图像都会调用一次 new Business();
。这意味着,如果您每页有多个图像,new Business();
将为此特定页面调用多次。
另外我强烈建议改变这个:
if (context.Request.QueryString["ListingID"] != null)
int listingID = Convert.ToInt32(context.Request.QueryString["ListingID"]);
与:
string listingIdParam = context.Request.QueryString["ListingID"];
if (listingIdParam != null)
int listingID = Convert.ToInt32(listingIdParam);
这将为您节省通常仅在重负载下才会出现的空引用异常。此外,上述内容将防止向请求提供错误的图像,尤其是当 isReusable 为 true 时。
我无法确定到底是什么问题,但我可以肯定地说,设置 isReusable 标志只是一种解决方法,并不能解决您的问题。此外,当此类问题仅在某些环境中可重现时,这意味着它是线程问题或请求处理存在一些差异(不同的 Web 服务器 - IIS6、IIS7、开发服务器)。
也许发布Business
类,它的构造函数可以提供一些启示。
此外,我建议实施某种错误日志记录以捕获处理程序中的异常并查看它们。
【讨论】:
伟大的输入 Branislav。有些图片根本不会渲染。今晚我将搜索原始代码并在这里发布,谢谢:) Branislav,我查了代码。显然,当我将 DataSet 换成 DataReader 时,我消除了对业务类的调用——对于读取二进制数据更有意义吗?我内联编写了 SQL 查询。这似乎解决了问题。【参考方案3】:如果您直接提供图像,请不要忘记设置正确的缓存标头,即 etags 和 expires。如果你不这样做,你真的会严重打击你的数据库并耗尽你的带宽。
您将需要处理以下 http 标头:
ETag 过期 最后修改 如果匹配 如果没有匹配 If-Modified-Since If-Unmodified-Since 除非-修改-自对于执行此检查的示例 http 处理程序: http://code.google.com/p/talifun-web/wiki/StaticFileHandler
【讨论】:
以上是关于使用 HttpHandler 流式传输数据库图像的主要内容,如果未能解决你的问题,请参考以下文章
使用 libavformat 通过 RTP 流式传输 H.264
使用 AVFoundation 在 iOS 上播放套接字流式传输的 h.264 电影
将 h.264 流包装在 mp.4 容器中并使用 nodejs 流式传输
使用 ffmpeg 从 C++ 内存中的多个图像流式传输 RTSP