我在ASP.NET中遇到了某种限制。 我将问题缩减为ASP.NET MVC项目中的示例项目(使用Visual Studio 2010和.NET 4创建),问题仍然存在:
在MVC控制器中,我有一个提供文件下载的方法:
public ActionResult DownloadBigFile()
{
string file = @"C:\Temp\File.txt";
var readStream = new FileStream(file, FileMode.Open, FileAccess.Read);
return File(readStream, "text/plain", "FILE");
}
当文件低于1 GB时,下载工作正常, 抛出1 GB以上的异常:“算术运算中出现溢出或下溢”,并带有以下详细信息:
Overflow or underflow in the arithmetic operation.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArithmeticException: Overflow or underflow in the arithmetic operation.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[ArithmeticException: Overflow or underflow in the arithmetic operation.]
[HttpException (0x80004005): An error occurred while communicating with the remote host. The error code is 0x80070216.]
System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect) +4081269
System.Web.Hosting.IIS7WorkerRequest.FlushCore(Boolean keepConnected, Int32 numBodyFragments, IntPtr[] bodyFragments, Int32[] bodyFragmentLengths, Int32[] bodyFragmentTypes) +12233777
System.Web.Hosting.IIS7WorkerRequest.FlushCachedResponse(Boolean isFinal) +847
System.Web.HttpResponse.UpdateNativeResponse(Boolean sendHeaders) +1110
System.Web.HttpRuntime.FinishRequestNotification(IIS7WorkerRequest wr, HttpContext context, RequestNotificationStatus& status) +336
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
问题是可重现的,但我没有找到有关此行为的任何信息。如何防止出现此类问题或如何管理大量下载(> 1GB)?
答案 0 :(得分:23)
在IIS中禁用缓冲可以完成任务:
public ActionResult DownloadBigFile()
{
string file = @"C:\Temp\File.txt";
var readStream = new FileStream(file, FileMode.Open, FileAccess.Read);
Response.BufferOutput = false; //<-----
return File(readStream, "text/plain", "FILE");
}
这真的很让我觉得为什么这不是返回文件时的默认ASP.Net MVC行为。特别是当用溪流做的时候。
答案 1 :(得分:0)
参考文献:
Download function failing with big file sizes
How to increase request timeout in IIS?
对我有用的东西
If File.Exists(file2return) Then
Dim finfo As New FileInfo(file2return)
Response.Clear()
Response.Buffer = False
Response.BufferOutput = False
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Length", finfo.Length.ToString)
Response.AddHeader("Content-Disposition", "attachment; filename=" + finfo.Name)
WriteBytesToResponseBuffered(file2return)
Response.End()
实际写入流输出的函数:
Private Sub WriteBytesToResponseBuffered(file2return As String)
Const MAX_BUFFER As Integer = 1024 ^ 2 ' = 1 048 576 bytes = 2^20 = 1 mebibyte = 1 MiB
Dim BytesRead As Integer = 0
Try
Dim Buffer As Byte() = New Byte(MAX_BUFFER - 1) {}
Using myFileStream As New FileStream(file2return, FileMode.Open, FileAccess.Read)
While (InlineAssignHelper(BytesRead, myFileStream.Read(Buffer, 0, MAX_BUFFER))) > 0
Response.OutputStream.Write(Buffer, 0, BytesRead)
End While
End Using
Catch ex As Exception
End Try
End Sub
Private Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function
web.config部分: 如果没有此服务,则该页面的投放将被终止(如果投放的时间过多)。仅当编译debug =“ false”
时,此参数才有效 <system.web>
<httpRuntime executionTimeout="600"/>
建议仅在提供文件的页面上更改此值。无需更改web.config,而是将其放在page_load上:
Page.Server.ScriptTimeout = 60 * 20 ' 20 minutes in this case
答案 2 :(得分:0)
如果要保存文件,请执行OutputStream,因此必须在.Save命令之前的一行禁用缓冲区,如下所示:
Response.BufferOutput = false; -- <- Must include this line before the Save method
_zip.Save(Response.OutputStream);
Response.Flush();
Response.End();