在ASP.NET中传输文件的最佳方法
什么是使用ASP.NETstream式处理文件的最佳方式?
似乎有各种各样的方法,并且我正在http处理程序中使用Response.TransmitFile()方法,该方法将文件直接发送到浏览器。 这用于各种各样的事情,包括从webroot外部发送FLV到embedded式Flashvideo播放器。
但是,这似乎不是一个可靠的方法。 特别是Internet Explorer(7)有一个奇怪的问题,浏览器在查看一个或两个video后就挂起了。 点击任何链接等都不起作用,而在网站上重新开始工作的唯一方法是closures浏览器并重新打开它。
在其他浏览器中也会出现这种情况,但是频率要低得多。 基于一些基本的testing,我怀疑这是与文件stream式传输的方式有关…也许连接没有被正确closures,或沿着这些线路。
在尝试了几个不同的事情之后,我发现以下方法适用于我:
Response.WriteFile(path); Response.Flush(); Response.Close(); Response.End();
这解决了上述问题,查看video不再导致Internet Explorer挂起。
不过,我的理解是, Response.WriteFile()首先将文件加载到内存中,并且考虑到一些正在stream式传输的文件可能会相当大,这似乎不是一个理想的解决scheme。
我有兴趣听听其他开发人员如何在ASP.NET中传输大型文件,特别是stream式传输FLVvideo文件。
我会采取“aspx”pipe道以外的东西。 特别是,我会写一个运行处理程序(ashx,或通过configuration映射),做最小的工作,并简单地写入到响应块。 处理程序将正常接受来自查询string/表单的input,find要对其进行stream式处理的对象,然后对数据进行stream式处理(在循环中使用适当大小的本地缓冲区)。 一个简单(不完整)的例子如下所示:
public void ProcessRequest(HttpContext context) { // read input etx context.Response.Buffer = false; context.Response.ContentType = "text/plain"; string path = @"c:\somefile.txt"; FileInfo file = new FileInfo(path); int len = (int)file.Length, bytes; context.Response.AppendHeader("content-length", len.ToString()); byte[] buffer = new byte[1024]; Stream outStream = context.Response.OutputStream; using(Stream stream = File.OpenRead(path)) { while (len > 0 && (bytes = stream.Read(buffer, 0, buffer.Length)) > 0) { outStream.Write(buffer, 0, bytes); len -= bytes; } } }
看看下面的文章在ASP.NET中跟踪和恢复大文件下载,这将给你更深入的,而不仅仅是打开一个stream和查找所有的位。
http协议支持范围字节请求和可继续下载,许多stream媒体客户端(如video播放器或Adobe pdf)可以并将尝试将这些请求分块,节省带宽并为用户提供更好的体验。
不是微不足道的,但花费的时间。
尝试打开文件作为stream,然后使用Response.OutputStream.Write()。 例如:
编辑:我不好,我忘了写需要一个字节的缓冲区。 固定
byte [] buffer = new byte[1<<16] // 64kb int bytesRead = 0; using(var file = File.OpenRead(path)) { while((bytesRead = file.Read(buffer, 0, buffer.Length)) != 0) { Response.OutputStream.Write(buffer, 0, bytesRead); } } Response.Flush(); Response.Close(); Response.End();
编辑2:你尝试过吗? 它应该工作。
尝试了很多不同的组合后,包括各种答案中发布的代码,看起来好像在调用TransmitFile之前设置Response.Buffer = true做了窍门,现在Web应用程序在Internet Explorer中响应更快。
在这种特殊情况下,SWF扩展也映射到ASP.NET,我们在我们的Web应用程序中使用自定义处理程序从磁盘读取文件,然后使用Response.TransmitFile()将其发送到浏览器。 我们有一个基于闪存的video播放器来播放video文件,这也是SWF的,我认为所有这些活动都是通过处理程序而不caching,这可能是在IE中引起奇怪的事情。