Загрузка 50 МБ файла из SQL Server в ASP.NET на некоторое время останавливается - PullRequest
2 голосов
/ 15 декабря 2010

Когда я пытаюсь загрузить файл размером 50 МБ из базы данных (это не проблема с меньшим размером файла), он иногда останавливается посередине и возобновляется через долгое время. Я что-то пишу?

код,

    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 ]

4 голосов
/ 15 декабря 2010
int ChunkSize = 262144;

Вот и все, это 25 МБ - прямо в середине загрузки 50 МБ. Попробуйте изменить это и посмотреть, что произойдет. По какой-то причине вы устанавливаете это значение?

3 голосов
/ 15 декабря 2010

Это не то, как вы транслируете контент из результата запроса SQL Server. Вы должны указать CommandBehavior.SequentialAccess:

Предоставляет DataReader возможность обрабатывать строки, содержащие столбцы с большие двоичные значения. Скорее, чем загрузка всего ряда, SequentialAccess включает DataReader для загрузки данных в виде потока. Затем вы можете использовать GetBytes или Метод GetChars для указания байта место для начала операции чтения, и ограниченный размер буфера для данных возвращается.

И, как уже отмечали другие, 25 МБ не является разумным размером порции буфера. Попробуйте что-то вроде 4K (типичный размер пакета TDS ) или 16k (типичный размер кадра SSL, если соединение зашифровано).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...