我们的Web应用程序(ASP.NET Web窗体)具有一个页面,该页面将向用户显示最近生成的PDF文件。由于PDF文件有时非常大,因此我们实现了“流式”方法,将其分批发送到客户端浏览器。
尽管按块向下发送数据,但在发送文件之前我们已经知道文件的完整大小,因此我们适当地设置了Content-Length标头。到今天为止,这已经在我们的生产环境中起作用了一段时间(并且在具有几乎相同的配置的测试环境中继续起作用)。所报告的问题是Chrome浏览器将尝试打开PDF文件,但由于“正在加载”动画卡住而挂起。
因为在我们的测试环境中一切仍然可以正常工作,所以我能够使用Firebug查看在两种环境中返回的响应头。在测试环境中,我看到一个适当的“ Content-Length”标头,而在生产环境中,该标头已被Transfer-Encoding:chunked标头取代。 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();
}
}
我很幸运在本地工作站上看到了相同的行为,因此使用调试器,我已经能够看到在第二个中设置了“ Transfer-Encoding:chunked”标头,并在调用“ Flush”的过程中通过了while循环。 。那时,响应同时具有Content-Length标头和Transfer-Encoding标头,但是当响应到达浏览器Firebug时,不知何故,它只显示了Transfer-Encoding标头。
更新
我想我已经将此归结为使用以下两种组合:在“块”中向下发送数据,并在HttpResponse对象上附加“过滤器”(我们正在使用过滤器跟踪向下发送到每个页面的viewstate的大小) 。将PDF向下发送到浏览器时,使用HTTP过滤器毫无意义,因此在此处清除过滤器已解决了我们的问题。我决定纯粹是出于好奇而深入研究,并更新了这个问题,以便将来任何其他人偶然发现此问题时。
我在AppHarbor上有了一个简单的应用程序,该应用程序再现了该问题:http://transferencodingtest.apphb.com/。如果您同时选中了“使用过滤器?”和“批量发送?”框,您应该可以看到显示了“传输编码:分块”标题(使用Chrome开发工具,Firebug,Fiddler等)。如果未选中任何一个框,则将获得正确的content-length标头。底层代码位于github上,因此您可以了解幕后情况:
https://github.com/appakz/TransferEncodingTest
请注意,要在本地进行复制,您需要在IIS 7.5中设置本地网站(7也可以,我没有尝试过)。 Visual Studio附带的ASP .NET开发服务器不能解决此问题。
我在此处的博客文章中添加了更多详细信息:'Content-Length' Header Replaced With 'Transfer-Encoding: Chunked' in ASP .NET
最佳答案
从an article on MSDN看来,您可以禁用分块编码:
appcmd set config /section:asp /enableChunkedEncoding:False
但是在ASP settings下提到了它,因此它可能不适用于从ASP.NET处理程序生成的响应。
关于asp.net - 为什么在手动刷新响应时,ASP.NET用Transfer-Encoding header 替换Content-Length header ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8582637/