在ASP.NET中流式传输大型文件上载

时间:2012-12-20 16:31:16

标签: asp.net asp.net-mvc file-upload

我有一个ASP.NET MVC应用程序,其页面允许用户上传文件。这些文件将是几百兆字节。

我在客户端使用FineUploader,如果浏览器支持它将使用FileAPI / XHR,否则将使用enctype =“multipart whatever”回退到iframe / form。

所以在服务器端我需要评估Request.Files.Count > 1。如果是true,这是一个旧学校上传,我将文件保存为Request.Files[0].InputStream.CopyTo(myFileStream),否则我会Request.InputStreawm.CopyTo(myFileStream)

以下是我编写的一些实际代码:https://github.com/ronnieoverby/file-uploader/blob/master/server/ASP.NET%20MVC%20C%23/FineUpload.cs

这一切都运行正常,但在我的测试中我注意到,在整个文件上传之前,ASP.NET MVC控制器操作和HttpHandler都不会开始处理,如果文件非常大,这是不好的,因为这意味着它是占用了很多Web服务器的RAM。

我发现这个:Streaming large file uploads to ASP.NET MVC听起来很有希望,但我真的不知道代码在他的应用程序中的位置。

所以,问题是:如何在上传仍在ASP.NET中时将上传的文件流式传输到磁盘上?

更新

我刚刚看到一个之前没有沉入的关键细节。来自HttpPostedFile文档:

  

默认情况下,所有请求,包括表单字段和上传文件,   大于256 KB的缓冲区被磁盘缓存,而不是保存在服务器中   存储器中。

好的,这解决了在大型上传期间Web服务器的RAM利用率可能会飙升的担忧。但是,仍然存在一个问题:在文件完全传输到Web服务器之后,服务器必须花时间将其移动到它的最终目的地。如果文件系统操作是副本(如果目标位于另一个物理磁盘上,则保证),则响应会不必要地延迟。

老实说,我可能会通过增加上传处理程序/操作的响应超时来解决这个问题。但是,将字节直接流式传输到目的地会很好。

2 个答案:

答案 0 :(得分:5)

您可以完全自定义的方式处理上传,而无需使用缓冲 HttpRequest.GetBufferlessInputStream方法。基本上,您可以访问原始传入数据,并随意使用它做任何事情。

我刚创建了一个小样本,它将原始请求内容保存到文件中:

  1. 创建处理程序:

    public class UploadHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            using (var stream = context.Request.GetBufferlessInputStream())
            using (var fileStream = File.Create("c:\\tempfile.txt"))
            {
                stream.CopyTo(fileStream);
            }
        }
        public bool IsReusable { get {  return true; } }
    }
    
  2. 在Web.config中注册:

    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <handlers>
            <add name="UploadHandler" verb="POST"
                path="/upload"
                type="UploadHandler"
            resourceType="Unspecified"/>
        </handlers>
    </system.webServer>
    
  3. 使用表单创建页面:

  4. <form action="/upload" method="post" enctype='multipart/form-data'>
         <input type="file" name="aa" id="aa"/>
         <input type="submit"/>
    </form>
    

答案 1 :(得分:0)

如果上传和流式传输耗尽了宝贵的服务器资源,那么您可能需要考虑在某种云上托管您的媒体文件。 ASP.NET可以使用Rackspace,Amazon Cloud API让您的用户将文件直接上传到CDN网络,然后以这种方式提供内容,我知道这不是回答您的问题,但很多人们会或已经拥有并且认为我得到了2美分。许多人仍然不选择使用云让我感到惊讶!一旦你去CDN,你永远不会回去。此外,对于大多数CDN,您还将获得上传容器的流媒体网址,其中它支持许多不同的电影类型,并且它的照明速度快,不仅可以让您的用户上传,而且您的上传速度也一直很慢。结果你的网站。