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

妖精的绣舞 提交于 2019-12-03 05:17:17

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.

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

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