大文件下载 - 与服务器重置连接

时间:2008-10-09 12:18:43

标签: asp.net download

我有一个asp.net网站,允许用户下载大文件--30mb到大约60mb。有时下载工作正常,但在下载完成之前,通常会在某些不同点失败,并显示与服务器的连接已重置的消息。

最初我只是使用Server.TransmitFile但是在读完之后我现在使用下面发布的代码。我还在Page_Init事件中将Server.ScriptTimeout值设置为3600。

private void DownloadFile(string fname, bool forceDownload)
        {
            string path = MapPath(fname);
            string name = Path.GetFileName(path);
            string ext = Path.GetExtension(path);
            string type = "";

            // set known types based on file extension  

            if (ext != null)
            {
                switch (ext.ToLower())
                {
                    case ".mp3":
                        type = "audio/mpeg";
                        break;

                    case ".htm":
                    case ".html":
                        type = "text/HTML";
                        break;

                    case ".txt":
                        type = "text/plain";
                        break;

                    case ".doc":
                    case ".rtf":
                        type = "Application/msword";
                        break;
                }
            }

            if (forceDownload)
            {
                Response.AppendHeader("content-disposition",
                    "attachment; filename=" + name.Replace(" ", "_"));
            }

            if (type != "")
            {
                Response.ContentType = type;
            }
            else
            {
                Response.ContentType = "application/x-msdownload";
            }

            System.IO.Stream iStream = null;

            // Buffer to read 10K bytes in chunk:
            byte[] buffer = new Byte[10000];

            // Length of the file:
            int length;

            // Total bytes to read:
            long dataToRead;

            try
            {
                // Open the file.
                iStream = new System.IO.FileStream(path, System.IO.FileMode.Open,
                            System.IO.FileAccess.Read, System.IO.FileShare.Read);


                // Total bytes to read:
                dataToRead = iStream.Length;

                //Response.ContentType = "application/octet-stream";
                //Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);

                // Read the bytes.
                while (dataToRead > 0)
                {
                    // Verify that the client is connected.
                    if (Response.IsClientConnected)
                    {
                        // Read the data in buffer.
                        length = iStream.Read(buffer, 0, 10000);

                        // Write the data to the current output stream.
                        Response.OutputStream.Write(buffer, 0, length);

                        // Flush the data to the HTML output.
                        Response.Flush();

                        buffer = new Byte[10000];
                        dataToRead = dataToRead - length;
                    }
                    else
                    {
                        //prevent infinite loop if user disconnects
                        dataToRead = -1;
                    }
                }
            }
            catch (Exception ex)
            {
                // Trap the error, if any.
                Response.Write("Error : " + ex.Message);
            }
            finally
            {
                if (iStream != null)
                {
                    //Close the file.
                    iStream.Close();
                }
                Response.Close();
            }

        }

4 个答案:

答案 0 :(得分:2)

威尔

<configuration>
  <system.web>
    <httpRuntime executionTimeout="3600"/>
  </system.web>
</configuration>

帮助什么?

写入数据的内部循环似乎有点复杂,我至少会将其更改为:

int length;
while(  Response.IsClientConnected && 
       (length=iStream.Read(buffer,0,buffer.Length))>0 ) 
{
  Response.OutputStream.Write(buffer,0,length);
  Response.Flush();
}

没有必要在循环中每次重新分配缓冲区,只需在将其写入输出后重新使用它。

进一步的改进是使用异步IO,但那是另一天。

答案 1 :(得分:2)

当我使用FileUpload Control时,我遇到了类似的问题,我上传的文件大小&gt; 4MB。我曾经得到'连接已重置'错误页面。这是我为解决问题而采取的步骤:

转到web.config文件并设置适合您希望上传的文件类型的大小限制。默认大小限制为4096千字节(KB)或4兆字节(MB)。您可以通过设置httpRuntime元素的maxRequestLength属性来允许上载更大的文件。要增加整个应用程序的最大允许文件大小,请在Web.config文件中设置maxRequestLength属性。

例如,允许使用10MB(10240 KB)文件。我使用(使用'&lt;'和']'替换'''与'&gt;'替换''')  [配置]
  [System.Web程序]
  [httpRuntime maxRequestLength =“10240”/]
  [/system.web]
[/配置]

答案 2 :(得分:0)

此问题的最终解决方法是在web.config文件中进行修改。我只需将sessionState mode =“InProc”更改为sessionState mode =“StateServer”。

答案 3 :(得分:0)

最终为我工作的是做一个Response.End并且还在文件流中使用using语句。这是我的代码:

public partial class ssl_Report_StreamReport : BaseReportPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Get the parameters
        string reportName = Utils.ParseStringRequest(Request, "reportName") ?? string.Empty;
        string reportGuid = Session["reportGuid"].ToString();
        string path = Path.Combine(ReportPath(), Utils.GetSessionReportName(reportName, reportGuid));

        using (var fileStream = File.Open(path, FileMode.Open))
        {
            Response.ClearHeaders();
            Response.Clear();
            Response.ContentType = "application/octet-stream";
            Response.AddHeader("Content-Disposition", "attachment; filename=\"" + reportName + "\"");
            Response.AddHeader("Content-Length", fileStream.Length.ToString(CultureInfo.InvariantCulture));
            StreamHelper.CopyStream(fileStream, Response.OutputStream);
            Response.Flush();
            Response.End();
        }

        ReportProcessor.ClearReport(Session.SessionID, path);
    }
}


public static class StreamHelper
{
    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            output.Write(buffer, 0, read);
        }
    }
}