Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
流式大文件上载到ASP.NET MVC_Asp.net_Asp.net Mvc_Upload_Streaming - Fatal编程技术网

流式大文件上载到ASP.NET MVC

流式大文件上载到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

对于我正在开发的应用程序,我需要允许用户通过我们的网站上传非常大的文件——也就是说,可能有很多GB。不幸的是,ASP.NET MVC似乎在开始服务之前将整个请求加载到RAM中——这对于这样的应用程序来说并不理想。值得注意的是,试图通过以下代码规避此问题:

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”应该表示什么?@KSwift87
cb
代表“字节计数”,这是Fog Creek的标准匈牙利符号。
request.ContentLength = clientRequest.InputStream.Length;
request.ContentLength = clientRequest.ContentLength;