使用 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

在 Internet Explorer 9 中使用 HTML5 实时流式传输 h.264

视频上传和流式传输(使用 Laravel VueJs 上传和显示所有类型的文件视频、图像、文档等)