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

后端 未结 3 851
攒了一身酷
攒了一身酷 2021-02-04 02:47

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

相关标签:
3条回答
  • 2021-02-04 03:22

    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
    0 讨论(0)
  • 2021-02-04 03:45

    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
    
    0 讨论(0)
  • 2021-02-04 03:46

    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();
    
    0 讨论(0)
提交回复
热议问题