ASP.NET Overflow or underflow in the arithmetic operation when returning large file bigger 1 GB

一个人想着一个人 提交于 2019-12-03 16:06:42

问题


I went across some sort of limitation in ASP.NET. I reduced the problem into a sample project in ASP.NET MVC Project (created with Visual Studio 2010 and .NET 4) and the problem still occurs:

In a MVC Controller I have a method which provides a file download:

public ActionResult DownloadBigFile()
{
    string file = @"C:\Temp\File.txt";
    var readStream = new FileStream(file, FileMode.Open, FileAccess.Read);
    return File(readStream, "text/plain", "FILE");
}

When the file is below 1 GB the download works fine, above 1 GB an exception is thrown: "Overflow or underflow in the arithmetic operation" with the following details:

 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 

The problem is reproducible but I did not find any information about this behavior. How can I prevent this kind of problem or how can I manage big downloads (> 1GB)?


回答1:


Disable buffering in IIS will do the job:

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");
}

It really beats me why this is not the default ASP.Net MVC behavior when returning files. Especially when doing it with streams.

  • Related thread in forums.iis.net
  • MSDN: HttpResponseBase.BufferOutput



回答2:


References:

Download function failing with big file sizes

How to increase request timeout in IIS?

https://msdn.microsoft.com/en-us/library/system.web.httpserverutility.scripttimeout%28v=vs.110%29.aspx

What worked for me:

            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()

The function that actually writes to the stream output:

    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

The web.config part: Without this the serving of the page would be terminated if the serving took too much time. This parameter only works when compilation debug="false"

  <system.web>
<httpRuntime executionTimeout="600"/>

It is advisable to change this value only for the page serving the file. Instead of changing web.config put this on the page_load:

Page.Server.ScriptTimeout = 60 * 20 ' 20 minutes in this case



回答3:


If you are saving a file do the OutputStream so you have to disable the buffer at a line before the .Save command, like this:

            Response.BufferOutput = false; -- <- Must include this line before the Save method
            _zip.Save(Response.OutputStream);
            Response.Flush();
            Response.End();


来源:https://stackoverflow.com/questions/22289200/asp-net-overflow-or-underflow-in-the-arithmetic-operation-when-returning-large-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!