流式大文件上载到ASP.NET MVC
对于我正在开发的应用程序,我需要允许用户通过我们的网站上传非常大的文件——也就是说,可能有很多GB。不幸的是,ASP.NET MVC似乎在开始服务之前将整个请求加载到RAM中——这对于这样的应用程序来说并不理想。值得注意的是,试图通过以下代码规避此问题:流式大文件上载到ASP.NET MVC,asp.net,asp.net-mvc,upload,streaming,Asp.net,Asp.net Mvc,Upload,Streaming,对于我正在开发的应用程序,我需要允许用户通过我们的网站上传非常大的文件——也就是说,可能有很多GB。不幸的是,ASP.NET MVC似乎在开始服务之前将整个请求加载到RAM中——这对于这样的应用程序来说并不理想。值得注意的是,试图通过以下代码规避此问题: if (request.Method == "POST") { request.ContentLength = clientRequest.InputStream.Length; var rgbBody = new byte[3
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。有没有一种简单的方法可以解决这个问题?当然,你可以这样做。看见我已经使用这种方法好几年了,有一个网站已经用至少几GB的文件进行了测试。本质上,您希望创建自己的IHttpHandler,这比听起来容易 简而言之,您创建了一个实现IHttpHandler的类 接口,这意味着您必须支持IsReusable属性和ProcessRequest方法。最重要的是,您的web.config有一个小小的改变,它就像一个魅力。在请求生命周期的这个阶段,上传的整个文件不会加载到内存中,因此它会巧妙地解决内存不足的问题 请注意,在web.config中
<httpHandlers>
<add verb="*" path="DocumentUploadService.upl" validate="false" type="TestUploadService.FileUploadHandler, TestUploadService"/>
</httpHandlers>
类,其中“文件以MIME多部分/表单数据格式上载。默认情况下,大于256 KB的所有请求(包括表单字段和上载的文件)都缓冲到磁盘,而不是保存在服务器内存中。”
if(context.Request.Files.Count>0)
{
字符串tempFile=context.Request.PhysicalApplicationPath;
for(int i=0;i0)
{
uploadFile.SaveAs(string.Format(“{0}{1}{2}”),
tempFile,“Upload\\”,uploadFile.FileName));
}
}
}
原来我最初的代码基本上是正确的;唯一需要的改变就是改变
request.ContentLength = clientRequest.InputStream.Length;
到
前一个流在整个请求中确定内容长度;后者仅检查内容长度
标题,这只要求标题已全部发送。这允许IIS几乎立即开始流式处理请求,从而完全消除了原始问题。您的代码看起来与我的代码几乎相同;唯一的区别是,我在ASP.NET MVC中运行它,而您直接在新的IHttpHandler中运行它。你知道为什么会有不同吗?在我的代码中是否有什么东西迫使流被拉入?您如何显示上载进度?我使用Flash文件上载器,这是将多个文件排队等待上载并获取上载状态的最佳方法。(例如)IHttpHandler方法非常有用。我已经在我的文件上传程序中集成了一个类似的解决方案。我需要使用GetBufferlessInputStream()来防止ASP.NET等待post数据完全上传。这里包含一些扩展的请求处理逻辑,因此,基本上只需触摸InputStream属性就可以破坏磁盘缓冲。有可能获得磁盘缓冲文件的流句柄吗?我还不能确定,但一旦我得到了一些有用的东西,我就不再认真研究这个问题了。你的代码在你的应用程序中驻留在哪里?控制器?处理程序?模块?我知道这个问题很老,但这是一个非常好的问题,我正在用它作为我正在进行的项目的参考。快速提问——变量cbRead中的“cb”应该表示什么?@KSwift87cb
代表“字节计数”,这是Fog Creek的标准匈牙利符号。
request.ContentLength = clientRequest.InputStream.Length;
request.ContentLength = clientRequest.ContentLength;