MVC 4.5.2中Response.WriteFile文件大小超过2GB

3
在测试的后期,我发现我的应用程序在发送超过 2 GB (Int32.MaxValue)的文件时出现了问题。有没有简单的方法来解决这个问题?这些是大型高清 .mov 电影文件。我在控制器中使用 Response.WriteFile 来确保浏览器不打开任何文件(大多数是不会被浏览器打开的大型视频文件,但并非全部),并强制下载以及执行一些日志记录。
目前,我的唯一选择是使用 ajax 进行基于 JavaScript 的记录,并直接链接到大型 mov 文件,但我希望避免在开发过程的这么晚更改我的记录方法,并且希望所有链接都使用一个记录方法,无论是需要使用 writefile 发送的文件,还是大型 mov 文件,都不会被浏览器打开,以简化操作。但似乎我没有太多选择。
阻止此类大文件传输的逻辑是什么?在堆栈跟踪中,我看到到处都是 Int64 大小,而不是 Int32,那么为什么它不起作用?
我正在使用最新的 MVC(4.5.2)和 VS2015。
当我请求一个大文件时,我得到以下错误:
[ArgumentOutOfRangeException: The size parameter must be between zero and the maximum Int32 value.
Parameter name: size
Actual value was 4563025348.]
   System.Web.HttpFileResponseElement..ctor(String filename, Int64 offset, Int64 size, Boolean isImpersonating, Boolean useTransmitFile, Boolean supportsLongTransmitFile) +3824261
   System.Web.HttpWriter.WriteFile(String filename, Int64 offset, Int64 size) +119
   System.Web.HttpResponse.WriteFile(String filename, Boolean readIntoMemory) +359
   System.Web.HttpResponseWrapper.WriteFile(String filename) +30

以下是我控制器代码与此相关的部分:

Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
Response.WriteFile(filePath);
Response.End();

谢谢

N.

编辑: 最终代码如下:

    using (FileStream fs = new FileStream(serverPath, FileMode.Open))
        {
            byte[] buffer = new byte[4096];
            int count = 0;

            Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
            while ((count = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                Response.OutputStream.Write(buffer, 0, count);
                Response.Flush();
            }
        }

HttpContext.ApplicationInstance.CompleteRequest();

既然是MVC,为什么不使用FileResult来完成你需要的功能呢? - Wiktor Zychla
我从未听说过它,我会调查一下。谢谢。 - Narcil
完美。对我来说,它可以传输超过8GB的文件。 - KMX
最好添加 FileAccess.Read 使用 (FileStream fs = new FileStream(filepath, FileMode.Open,FileAccess.Read)) - 3WA羽山秋人
1个回答

3

通常情况下,使用流来下载文件。这样,在任何时间点上,整个文件(2GB!)都不会加载到内存中。如果有100个用户同时请求文件,这将需要多少内存。

相反,您应该通过流(FileStream)读取文件,并将此流直接写入用户的响应中。

像这样:

//assuming you have your FileStream handle already - named fs
byte[] buffer = new byte[4096];
long count = 0;

while ((count = fs.Read(buffer, 0, buffer.Length)) > 0)
{
    response.OutputStream.Write(buffer, 0, count);
    response.Flush();
}

查看此答案-将PDF流写入响应流


请帮我处理这个踩票问题。告诉我出了什么问题,怎样解决它。请给我一些建议。 - Parv Sharma
哈哈,我没有给你点踩啊伙计。一定是有人恶意操作了。这里送你一个赞 :) 我正在测试中,会尽快报告结果。 - Narcil
1
在调用write方法时,我得到了“无法将long转换为int”的错误,该错误是关于count参数的。 - Narcil
看起来运行得很好。目前正在从我的本地机器下载一个4G的文件,希望在我无法从这里访问的生产服务器上也能正常工作。谢谢! - Narcil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接