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

18

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

asp.net
arithmeticexception
asked on Stack Overflow Mar 9, 2014 by Alex • edited Mar 1, 2018 by Uwe Keim

3 Answers

28

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.

answered on Stack Overflow Feb 27, 2015 by Stefan Sieber
0

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
answered on Stack Overflow Jul 9, 2018 by Manuel Alves • edited Jul 9, 2018 by Manuel Alves
0

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();
answered on Stack Overflow Jan 11, 2019 by Gustavo Rocha Dias

User contributions licensed under CC BY-SA 3.0