从ASP.NET中的SQL Server下载50 MB文件在中间停止一段时间

时间:2010-12-15 16:31:22

标签: c# asp.net sql

当我尝试从数据库下载50 MB文件时(这不是文件较小的问题),它会在中间停止,并在很长一段时间后再次恢复。我在忙什么?

代码,

    SqlConnection con = new SqlConnection(ConnectionString);
    SqlCommand cmd = new SqlCommand("DownloadFile", con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandTimeout = 60;

    cmd.Parameters.AddWithValue("@Id", Id);

    try
    {
        conPortal.Open();
        SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);

        // File name
        string fileName = reader.GetString(0);

        // Total bytes to read
        int dataToRead = reader.GetInt32(1);

        Context.Server.ScriptTimeout = 600;
        Context.Response.Buffer = true;
        Context.Response.Clear();

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

        Context.Response.AddHeader("Content-Length", dataToRead.ToString());

        int ChunkSize = 262144;

        // Buffer to read 10K bytes in chunk
        byte[] buffer = new Byte[ChunkSize];
        long offset = 0;
        long length;

        // Read the bytes.
        while (dataToRead > 0)
        {
            // Verify that the client is connected.
            if (Context.Response.IsClientConnected)
            {
                // Read the data in buffer
                length = reader.GetBytes(2, offset, buffer, 0, ChunkSize);
                offset += ChunkSize;

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

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

                buffer = new Byte[ChunkSize];
                dataToRead = dataToRead - (int) length;
            }
            else
            {
                //prevent infinite loop if user disconnects
                dataToRead = -1;
            }
        }
    }
    finally
    {
        cmd.Dispose();
    }

2 个答案:

答案 0 :(得分:4)

int ChunkSize = 262144;

你去,那是25 MB - 正好在50 MB下载的中间。尝试修改它,看看会发生什么。您将其设置为该特定值的任何原因?

答案 1 :(得分:3)

这不是您从SQL Server查询结果中流式传输内容的方式。您必须指定CommandBehavior.SequentialAccess

  

为DataReader提供了一种方法   处理包含列的行   大二进制值。而不是   加载整行,   SequentialAccess启用   DataReader将数据作为流加载。   然后,您可以使用GetBytes或   GetChars方法指定一个字节   开始读取操作的位置,   以及数据的有限缓冲区大小   被退回。

并且,正如其他人所指出的,25MB不是合理的缓冲块大小。尝试类似4K(典型TDS packet size)或16k(如果连接已加密,则为典型的SSL帧大小)。