为什么在手动刷新响应时 ASP.NET 将 Content-Length 标头替换为 Transfer-Encoding 标头?

2024-03-17

我们的 Web 应用程序(ASP.NET Web Forms)有一个页面,将向用户显示最近生成的 PDF 文件。由于 PDF 文件有时非常大,因此我们实现了一种“流式传输”方法,将其分块发送到客户端浏览器。

尽管以块的形式发送数据,但我们在发送之前知道文件的完整大小,因此我们适当地设置 Content-Length 标头。直到今天,它已经在我们的生产环境中运行了一段时间(并且继续在我们的测试环境中以几乎相同的配置运行)。报告的问题是 Chrome 会尝试打开 PDF 文件,但会因“正在加载”动画卡住而挂起。

因为在我们的测试环境中一切仍然工作正常,所以我能够使用 Firebug 查看在两个环境中返回的响应标头。在测试环境中,我看到了正确的“Content-Length”标头,而在生产中已被替换为传输编码:分块标头。 Chrome 不喜欢这样,因此挂断了。

我读过一些文章和帖子,讨论在未提供 Content-Length 标头时如何显示 Transfer-Encoding 标头,但我们指定了 Content-Length 标头,并且在为测试服务器上的相同 PDF 文件。

测试服务器和生产服务器都运行 IIS 7.5,并且都启用了动态和静态压缩。

这是有问题的代码:

var fileInfo = new FileInfo(fileToSendDown);
Response.ClearHeaders();
Response.ContentType = "application/pdf";            
Response.AddHeader("Content-Disposition", "filename=test.pdf");
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
var buffer = new byte[1024];
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    int read;
    while ((read = fs.Read(buffer, 0, 1024)) > 0)
    {
        if (!response.IsClientConnected) break;
        Response.OutputStream.Write(buffer, 0, read);
        Response.Flush();
    }
}

我很幸运在本地工作站上看到了相同的行为,因此使用调试器我能够看到在调用“Flush”期间第二次通过 while 循环时设置了“Transfer-Encoding: chunked”标头。此时,响应同时具有 Content-Length 标头和 Transfer-Encoding 标头,但不知何故,当响应到达浏览器时,Firebug 只显示 Transfer-Encoding 标头。

UPDATE

我想我已经追踪到使用以“块”形式发送数据并将“过滤器”附加到 HttpResponse 对象的组合(我们使用过滤器来跟踪发送到每个页面的视图状态的大小) 。将 PDF 发送到浏览器时使用 HTTP 过滤器是没有意义的,因此清除此处的过滤器可以解决我们的问题。我决定纯粹出于好奇而更深入地研究,并更新了这个问题,以防其他人将来偶然发现这个问题。

我在 AppHarbor 上有一个简单的应用程序可以重现该问题:http://transferencodingtest.apphb.com/ http://transferencodingtest.apphb.com/。如果您同时选中“使用过滤器?”和“发送块?”您应该能够看到“transfer-encoding: chunked”标头出现(使用 Chrome 开发工具、Firebug、Fiddler 等)。如果未选中其中任何一个框,您将获得正确的内容长度标头。底层代码位于 github 上,因此您可以看到幕后发生的事情:

https://github.com/appakz/TransferEncodingTest https://github.com/appakz/TransferEncodingTest

请注意,要在本地重现,您需要在 IIS 7.5 中设置本地网站(7 也可能有效,我还没有尝试过)。 Visual Studio 附带的 ASP .NET 开发服务器不会重现该问题。

我在此处的博客文章中添加了更多详细信息:ASP .NET 中的“Content-Length”标头替换为“Transfer-Encoding: Chunked” http://gruffcode.com/2012/01/02/content-length-header-replaced-with-transfer-encoding-chunked-in-asp-net/


From MSDN 上的一篇文章 http://technet.microsoft.com/nl-nl/library/cc730855%28WS.10%29.aspx看来您可以禁用分块编码:

appcmd set config /section:asp /enableChunkedEncoding:False

但下面提到了ASP 设置 http://www.iis.net/ConfigReference/system.webServer/asp,因此它可能不适用于从 ASP.NET 处理程序生成的响应。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在手动刷新响应时 ASP.NET 将 Content-Length 标头替换为 Transfer-Encoding 标头? 的相关文章

随机推荐