如何在 ASP.NET Response 中传送大文件? [英] How to deliver big files in ASP.NET Response?

查看:16
本文介绍了如何在 ASP.NET Response 中传送大文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不是在寻找任何替代流媒体文件内容的方法数据库,确实我正在寻找问题的根源,这是运行文件直到 IIS 6,我们在经典模式下运行我们的应用程序,现在我们将我们的 IIS 升级到 7,我们正在管道模式下运行应用程序池和这个问题开始了.

I am not looking for any alternative of streaming file contents from database, indeed I am looking for root of the problem, this was running file till IIS 6 where we ran our app in classic mode, now we upgraded our IIS to 7 and we are running app pool in pipeline mode and this problem started.

我有一个处理程序,我必须将大文件交付给客户端请求.我面临以下问题,

I have an handler, where I have to deliver big files to client request. And I face following problems,

文件的平均大小为 4 到 100 MB,因此让我们考虑 80MB 的文件下载情况.

Files are of average size 4 to 100 MB, so lets consider 80MB file download case.

缓冲开启,缓慢启动

Response.BufferOutput = True;

这导致文件启动很慢,因为用户下载甚至进度条直到几秒钟才出现,通常是 3 到 20 秒,背后的原因是,IIS 首先读取整个文件,确定内容长度然后开始文件传输.文件正在视频播放器中播放,运行速度非常慢,但 iPad 只先下载文件的一小部分,因此运行速度很快.

This results in very slow start of file, as user downloads and even progress bar does not appear till few seconds, typically 3 to 20 seconds, reason behind is, IIS reads entire file first, determines the content-length and then begin the file transfer. File is being played in video player, and it runs very very slow, however iPad only downloads fraction of file first so it works fast.

缓冲关闭,无内容长度,快速启动,无进展

Reponse.BufferOutput = False;

这会导致立即启动,但是最终客户端(典型的浏览器,如 Chrome)不知道内容长度,因为 IIS 也不知道,因此它不显示进度,而是显示已下载 X KB.

This results in immediate start, however end client (typical browser like Chrome) does not know Content-Length as IIS does not know either, so it does not display progress, instead it says X KB downloaded.

缓冲关闭、手动内容长度、快速启动、进度和协议违规

Response.BufferOutput = False;
Response.AddHeader("Content-Length", file.Length);

这会导致在 Chrome 等中立即正确下载文件,但是在某些情况下,IIS 处理程序会导致远程客户端关闭连接"错误(这种情况非常频繁),而其他 WebClient 会导致协议违反.这种情况发生在所有请求的 5% 到 10%,而不是每个请求.

This results in correct immediate file download in Chrome etc, however in some cases IIS handler results in "Remote Client Closed Connection" error (this is very frequent) and other WebClient results in protocol violation. This happens 5 to 10% of all requests, not every requests.

我猜正在发生的事情是,当我们不进行缓冲并且客户端可能断开连接而不期望任何输出时,IIS 不会发送任何称为 100 continue 的内容.然而,从源代码读取文件可能需要更长的时间,但在客户端我增加了超时但似乎 IIS 超时并且无法控制.

I guess what is happening is, IIS does not send anything called 100 continue when we dont do buffering and client might disconnect not expecting any output. However, reading files from source may take longer time, but at client side I have increased timeout but seems like IIS timesout and have no control.

无论如何我可以强制 Response 发送 100 continue 并且不让任何人关闭连接吗?

Is there anyway I can force Response to send 100 continue and not let anyone close the connection?

更新

我在 Firefox/Chrome 中发现了以下标头,此处似乎没有违反协议或错误标头的异常情况.

I found following headers in Firefox/Chrome, nothing seems unusual here for Protocol Violation or Bad Header.

Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:POST, GET, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000
Cache-Control:private
Content-Disposition:attachment; filename="24.jpg"
Content-Length:22355
Content-Type:image/pjpeg
Date:Wed, 07 Mar 2012 13:40:26 GMT
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

更新 2

Turning Recycling 仍然没有提供太多,但我已将 MaxWorkerProcess 增加到 8,并且我现在得到的错误数量比以前更少.

Turning Recycling still did not offer much but I have increased my MaxWorkerProcess to 8 and I now get less number of errors then before.

但平均而言,在一秒内 200 个请求中,有 2 到 10 个请求失败......而且这种情况几乎每隔几秒就会发生一次.

But on an average, out of 200 requests in one second, 2 to 10 requests fail.., and this happens on almost every alternate seconds.

更新 3

继续 5% 的请求失败并显示服务器违反协议.Section=ResponseStatusLine",我有另一个程序从使用 WebClient 的网络服务器下载内容,并且每秒出现 4-5 次此错误,在我平均有 5% 的请求失败.有没有办法跟踪 WebClient 故障?

Continuing 5% of requests failing with "The server committed a protocol violation. Section=ResponseStatusLine", I have another program that downloads content from the webserver which uses WebClient, and which gives this error 4-5 times a second, on an average I have 5% of requests failing. Is there anyway to trace WebClient failure?

重新定义问题

接收到零字节文件

IIS 出于某种原因关闭了连接,在 WebConfig 的客户端,我收到 0 字节的文件,它不是零字节,我们进行 SHA1 哈希检查,这告诉我们在 IIS Web 服务器中,没有记录错误.

IIS closes connection for some reason, on client side in WebConfig, I receive 0 bytes for the file which is not zero bytes, We do SHA1 hash check, this told us that in IIS web server, no error is recorded.

这是我的错误,它在我们使用实体框架时得到解决,它正在读取脏(未提交的行),因为读取不在事务范围内,将其放在事务范围内解决了这个问题.

This was my mistake, and its resolved as we are using Entity Framework, it was reading dirty (uncommitted rows) as read was not in transaction scope, putting it in transaction scope has resolved this issue.

引发协议违反异常

WebClient 抛出 WebException 说服务器违反了协议.Section=ResponseStatusLine.

WebClient throws WebException saying "The server committed a protocol violation. Section=ResponseStatusLine.

我知道我可以启用不安全的标头解析,但这不是重点,当我的 HTTP 处理程序发送正确的标头时,不知道为什么 IIS 发送任何额外的东西(在 firefox 和 chrome 上检查,没有异常),这仅发生 2% 的次数.

I know I can enable unsafe header parsing but that is not the point, when it is my HTTP Handler that is sending proper headers, dont know why IIS is sending anything extra (checked on firefox and chrome, nothing unusual), this happens only 2% of times.

更新 4

发现 sc-win32 64 错误,我在某处读到 MinBytesPerSecond 的 WebLimits 必须从 240 更改为 0,但一切仍然相同.但是我注意到,每当 IIS 记录 64 sc-win32 错误时,IIS 都会将 HTTP 状态记录为 200,但会出现一些错误.现在我无法为 200 开启 Failed Trace Logging,因为它会导致大量文件.

Found sc-win32 64 error and I read somewhere that WebLimits for MinBytesPerSecond must be changed from 240 to 0, still everything is same. However I have noticed that whenever IIS logs 64 sc-win32 error, IIS records HTTP Status as 200 but there was some error. Now I cant turn on Failed Trace Logging for 200 because it will result in massive files.

通过增加 MinBytesPerSecond 和禁用 Sessions 解决了上述两个问题,我添加了总结每个要点的详细答案.

Both of above problems were solved by increasing MinBytesPerSecond and as well as disabling Sessions, I have added detailed answer summarizing every point.

推荐答案

虽然在 IIS 中传递大文件的正确方法是以下选项,

Although correct way to deliver the big files in IIS is the following option,

  1. 在 WebLimits 中将 MinBytesPerSecond 设置为零(这肯定有助于提高性能,因为 IIS 选择关闭持有 KeepAlive 连接的客户端,传输量较小)
  2. 向应用程序池分配更多工作进程,我已设置为 8,现在仅当您的服务器正在分发更大的文件时才应该这样做.这肯定会导致其他网站的执行速度变慢,但这将确保更好的交付.我们已设置为 8,因为该服务器只有一个网站,而且它只会传送大量文件.
  3. 关闭应用程序池回收
  4. 关闭会话
  5. 保持缓冲状态
  6. 在执行以下每个步骤之前,请检查 Response.IsClientConnected 是否为 true,否则放弃并且不发送任何内容.
  7. 在发送文件前设置 Content-Length
  8. 刷新响应
  9. 写入输出流,并定期刷新

这篇关于如何在 ASP.NET Response 中传送大文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆