如何实现在ASP.NET响应大文件? [英] How to deliver big files in ASP.NET Response?

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

问题描述


  

我不希望从流媒体文件的内容任何替代
  数据库,事实上,我正在寻找问题的根源,这是
  运行文件到IIS 6,我们跑了我们在经典模式的应用程序,现在我们
  升级了我们的IIS 7,我们正在运行的管道模式应用程序池和
  这个问题开始了。


我有一个处理程序,在那里我有大的文件传送到客户端的请求。而我面对以下问题,

文件的平均大小4到100 MB,所以让我们考虑80MB文件下载情况。

缓冲开,慢启动

  Response.BufferOutput = TRUE;

这会导致文件非常缓慢的开始,因为用户下载甚至是进度条不出现,直到几秒钟时间,通常为3到20秒,背后的原因是,IIS首先读取整个文件,确定内容长度,然后开始文件传输。文件正在播放的视频播放器,它运行的文件首先非常非常慢,不过仅限iPad下载分数所以它的工作原理快。

缓冲关,没有内容长度,启动速度快,无进度

  Reponse.BufferOutput = FALSE;

这将会立即启动,但最终客户(如Chrome浏览器的典型),不知道内容长度为IIS也也不知道,所以它不显示进度,而是说点¯xKB下载。

缓冲关,手册内容长度,快速启动,进展及违反协议

  Response.BufferOutput = FALSE;
Response.AddHeader(内容长度,file.Length);

这导致在Chrome等正确的即时文件下载,但在某些情况下,IIS中的远程客户端关闭连接的错误处理的结果(这是很常见的)以及违反协议的其它Web客户端的结果。 这种情况发生的所有请求,不是每个请求的5%至10%。

我猜发生了什么事是,IIS不发送任何所谓的100继续,当我们不这样做缓冲,客户端可能会断开连接不期待任何输出。然而,从源读取文件可能需要更长的时间,但在客户端我增加超时,但似乎IIS timesout并没有控制。

反正我有可以强制回应送100继续不让任何人关闭连接?

更新

我发现下面的在Firefox / Chrome的头,没有什么看似寻常这里违反协议或坏头。

 接入控制允许标题:*
访问控制允许的方法:POST,GET,OPTIONS
访问控制允许来源:*
访问控制,最大年龄:1728000
缓存控制:私人
内容处置:附件;文件名=24.jpg
内容长度:22355
内容类型:图像/ PJPEG
日期:星期三,2012年3月7日13点40分26秒GMT
服务器:Microsoft-IIS / 7.5
的X ASPNET-版本:4.0.30319
的X已启动方式:ASP.NET

更新2

至于回收仍然没有提供多少,但我有我的MaxWorkerProcess增至8,我现在得到较少的错误编号,然后之前。

可是,在一个平均,出在一秒200请求的,2至10个请求失败..,这发生在几乎每一个备用秒

更新3

继续与失败请求的5%的服务器犯了违反协议。部分= ResponseStatusLine,我还有一个程序,从下载它使用Web客户端Web服务器的内容,这给这个错误第二个4-5次,上平均我请求失败的5%。反正是有跟踪Web客户端失败?

重新定义问题

零字节文件接收

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


  

这是我的失误,其解决,因为我们使用的是实体框架,它在读脏(未提交行)为已读在交易范围是不是,把它在交易范围已经解决了这个问题。


协议冲突发生异常

Web客户端抛出引发WebException说:服务器犯了违反协议。部分= ResponseStatusLine。

我知道我可以使不安全的头分析但这不是重点,当它是发送正确的头我的HTTP处理程序,不知道为什么IIS发送额外的东西(在Firefox和Chrome检查,没有什么不寻常),这恰好只有2%的时候。

更新4

找到SC-64的Win32错误,我读的地方,为MinBytesPerSecond WebLimits必须改变,从240到0,仍然一切都是一样的。不过我注意到,每当IIS日志64 SC-Win32错误,IIS记录HTTP状态为200,但有一些错误。现在我无法打开无法跟踪记录200,因为它会导致大规模的文件。


  

这两个以上的问题都通过增加MinBytesPerSecond和以及禁用会议解决了,我已经添加了详细的解答,总结每一点。



解决方案

虽然提供IIS中的大文件,正确的方法是下面的选项,


  1. 设置MinBytesPerSecond零在WebLimits(这将在提升性能肯定有所帮助,如IIS选择关闭客户保持更小尺寸的KeepAlive传输连接)

  2. 分配更多的工作进程的应用程序池,我已经设置为8,现在这个应该只如果你的服务器分发较大的文件进行。这必将导致其他网站执行慢,但是这将确保更好的交付。我们已经设置为8,因为这服务器只有一个网站,它只是提供了巨大的文件。

  3. 关闭应用程序池回收

  4. 关闭会话

  5. 将缓冲

  6. 每个以下步骤之前,请检查Response.IsClientConnected是真实的,否则放弃和不发送任何东西。

  7. 发送文件之前设置的Content-Length

  8. 刷新响应

  9. 写入到输出流,并在冲洗定期

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,

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

Buffering On, Slow Start

Response.BufferOutput = True;

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.

Buffering Off, No Content-Length, Fast Start, No Progress

Reponse.BufferOutput = False;

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.

Buffering Off, Manual Content-Length, Fast Start, Progress and Protocol Violation

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

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.

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.

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

UPDATE

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

UPDATE 2

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.

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

UPDATE 3

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?

Problems Redefined

Zero Byte File Received

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.

Protocol Violation Exception Raised

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

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.

UPDATE 4

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.

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

解决方案

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

  1. Set MinBytesPerSecond to Zero in WebLimits (This will certainly help in improving performance, as IIS chooses to close clients holding KeepAlive connections with smaller size transfers)
  2. Allocate More Worker Process to Application Pool, I have set to 8, now this should be done only if your server is distributing larger files. This will certainly cause other sites to perform slower, but this will ensure better deliveries. We have set to 8 as this server has only one website and it just delivers huge files.
  3. Turn off App Pool Recycling
  4. Turn off Sessions
  5. Leave Buffering On
  6. Before each of following steps, check if Response.IsClientConnected is true, else give up and dont send anything.
  7. Set Content-Length before sending the file
  8. Flush the Response
  9. Write to Output Stream, and Flush in regular intervals

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

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