在ASP.NET中流式传输文件的最佳方式

Mun*_*Mun 34 asp.net flash streaming video-streaming

使用ASP.NET流式传输文件的最佳方法是什么?

似乎有各种方法,我目前在http处理程序中使用Response.TransmitFile()方法,该方法直接将文件发送到浏览器.这用于各种事情,包括从Webroot外部发送FLV到嵌入式Flash视频播放器.

但是,这似乎不是一种可靠的方法.特别是,Internet Explorer(7)存在一个奇怪的问题,浏览器只是在观看一两个视频后挂起.单击任何链接等都没有任何效果,并且在网站上重新运行工作的唯一方法是关闭浏览器并重新打开它.

这在其他浏览器中也会发生,但更不频繁.基于一些基本的测试,我怀疑这与文件流的方式有关...也许连接没有正确关闭,或者沿着这些线路.

在尝试了几个不同的东西后,我发现以下方法对我有用:

Response.WriteFile(path);
Response.Flush();
Response.Close();
Response.End();
Run Code Online (Sandbox Code Playgroud)

这解决了上述问题,查看视频不再导致Internet Explorer挂起.

但是,我的理解是Response.WriteFile()首先将文件加载到内存中,并且假设流式传输的某些文件可能非常大,这似乎不是一个理想的解决方案.

我很想知道其他开发人员如何在ASP.NET中传输大文件,特别是流式传输FLV视频文件.

Mar*_*ell 51

我会把事情放在"aspx"管道之外.特别是,我会编写一个运行处理程序(ashx,或通过配置映射),它执行最小的工作,并简单地以块的形式写入响应.处理程序将正常接受来自查询字符串/表单的输入,定位要流的对象,并流式传输数据(在循环中使用中等大小的本地缓冲区).一个简单(不完整)的例子如下所示:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Rob*_*son 10

看一下下面的文章跟踪和恢复ASP.NET中的大文件下载,它将为您提供更深入的内容,而不仅仅是打开流并删除所有位.

http协议支持远程字节请求和可恢复下载,许多流媒体客户端(如视频播放器或Adobe pdf)可以并且将尝试将这些内容组合起来,从而节省带宽并为用户提供更好的体验.

不是微不足道的,但现在是时候花得很好了.


Ran*_*pho 8

尝试将文件作为流打开,然后使用Response.OutputStream.Write().例如:

编辑:我的不好,我忘记了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();
Run Code Online (Sandbox Code Playgroud)

编辑2:你试过这个吗?它应该工作.

  • 关于字节数组 - 您不必将整个流加载到内存中.我在流媒体中使用的代码最多只有64kb的内存(加上微小的开销). (2认同)