2009-06-25 93 views
55

对于应用程序我的工作,我需要让用户上传非常大的文件 - 即,许多潜在的千兆字节 - 通过我们的网站。不幸的是,ASP.NET MVC似乎在开始提供服务之前将整个请求加载到RAM中 - 这对于这样的应用程序来说并不完美。值得注意的是,试图绕过通过代码的问题,如下列:流大文件上传到ASP.NET MVC

if (request.Method == "POST") 
{ 
    request.ContentLength = clientRequest.InputStream.Length; 
    var rgbBody = new byte[32768]; 

    using (var requestStream = request.GetRequestStream()) 
    { 
     int cbRead; 
     while ((cbRead = clientRequest.InputStream.Read(rgbBody, 0, rgbBody.Length)) > 0) 
     { 
      fileStream.Write(rgbBody, 0, cbRead); 
     } 
    } 
} 

无法规避缓冲区的请求,到-RAM的心态。有没有简单的方法来解决这个问题?

+1

哪里你的代码驻留在你的应用程序?控制器?处理程序?模块? – 2012-12-20 16:02:32

+0

我知道这个问题是旧的,但它是我使用的是作为一个项目,我工作的一个参考一个很好的问题。快速的问题 - 什么是“cb”应该表示在你的变量cbRead中? – KSwift87 2012-12-21 22:43:00

+0

@ KSwift87`cb`代表“字节计数”,这是在雾溪标准应用匈牙利命名法。 – 2012-12-23 21:41:42

回答

23

事实证明,我的初始代码基本上是正确的;所需的唯一改变是改变

request.ContentLength = clientRequest.InputStream.Length; 

request.ContentLength = clientRequest.ContentLength; 

在确定内容长度整个请求前者流;后者仅检查标头,这只需要标头已被完整发送。这允许IIS几乎立即开始流式传输请求,这完全消除了原始问题。

14

当然,你可以做到这一点。请参阅RESTful file uploads with HttpWebRequest and IHttpHandler。我一直在使用这种方法几年,并有一个网站已经测试了至少几千兆字节的文件。实质上,你想创建自己的IHttpHandler,比听起来容易。

简而言之,您创建一个实现IHttpHandler 接口,这意味着你必须支持IsReusable属性和ProcessRequest方法的类。最重要的是,你的web.config有一个小的改变,它就像一个魅力。在请求的生命周期的这个阶段,上传的整个文件不会被加载到内存中,因此它整齐地解决了内存不足的问题。

注意,在web.config中,

<httpHandlers> 
<add verb="*" path="DocumentUploadService.upl" validate="false" type="TestUploadService.FileUploadHandler, TestUploadService"/> 
</httpHandlers> 

文件引用,DocumentUploadService.upl,实际上并不存在。这只是为了给予一个备用扩展,以便该请求不被标准处理程序拦截。您将文件上传表单指向该路径,但随后您的FileUploadHandler类将启动并实际接收该文件。

更新:其实,我使用的代码与该文章不同,我想我偶然发现它的工作原理。我用的是HttpPostedFile类,其中“文件在MIME的multipart/form-data的格式上传。默认情况下,所有的请求,包括表单字段和上传文件,大于256 KB的缓存到磁盘上,而不是在服务器内存中“。

if (context.Request.Files.Count > 0) 
{ 
    string tempFile = context.Request.PhysicalApplicationPath; 
    for(int i = 0; i < context.Request.Files.Count; i++) 
    { 
     HttpPostedFile uploadFile = context.Request.Files[i]; 
     if (uploadFile.ContentLength > 0) 
     { 
      uploadFile.SaveAs(string.Format("{0}{1}{2}", 
       tempFile,"Upload\\", uploadFile.FileName)); 
     } 
    } 
}