2010-01-22 1 views
5

На сайте ASP.net на моем рабочем месте отвечает за обработку файлов (ПРИМЕЧАНИЕ: Response.TransmitFile здесь не используется, поскольку содержимое загрузки будучи потоковым из архива):Использование памяти ASP.net во время загрузки

private void DownloadFile(Stream stream) 
{ 
     int bytesRead; 
     int chunkSize = 1048576; //1MB 

     byte[] readBuffer = new byte[chunkSize]; 
     while ((bytesRead = stream.Read(readBuffer, 0, readBuffer.Length)) != 0) 
      { 
       if(!Response.IsClientConnected) 
        break; 
       byte[] chunk = new byte[bytesRead]; 
       Array.Copy(readBuffer,0,chunk,0,bytesRead); 
       Response.BinaryWrite(chunk); 
       Response.Flush(); 
     } 
     stream.Close(); 
} 

Наши пользователи часто загружают мульти-сотни МБ файлов, которые могут жевать память сервера довольно быстро. Мое предположение заключается в том, что это связано с буферизацией ответа. Имеет ли это смысл?

Я только что прочитал о свойстве «buffer» объекта Response. Если я установил значение false, предотвратит ли вызов Response.BinaryWrite() буферизацию данных в памяти? В общем, что такое хороший способ ограничить использование памяти в этой ситуации? Возможно, я должен перевести из zip во временный файл, а затем вызвать Response.TransmitFile()?

EDIT: В дополнение к возможным решениям, я очень заинтересован в объяснении проблемы использования памяти, присутствующей в приведенном выше коде. Почему это потребляет намного больше 1 МБ, хотя Response.Flush вызывается на каждой итерации цикла? Это просто ненужное распределение кучи, которое происходит на каждой итерации цикла (и сразу не получает GC'd), или есть что-то еще на работе?

ответ

4

Вот несколько кодов, над которыми я работаю для этого. Он использует буфер размером 8000 байт, чтобы отправить файл в куски. Некоторое неофициальное тестирование в большом файле показало значительное уменьшение выделенной памяти.

int BufferSize = 8000; 
FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
try { 
    long fileSize = stream.Length; 

    long dataLeftToRead = fileSize; 
    int chunkLength; 
    buffer = new Byte[BufferSize]; 

    while (dataLeftToRead > 0) { 
    if (!Response.IsClientConnected) { 
     break; 
    } 
    chunkLength = stream.Read(buffer, 0, BufferSize); 

    Response.OutputStream.Write(buffer, 0, chunkLength); 
    Response.Flush(); 

    dataLeftToRead -= chunkLength; 
    } 
} 
finally { 
    if (stream != null) { 
    stream.Close(); 
} 

отредактирован, чтобы исправить ошибку синтаксиса и отсутствующее значение

+0

педант комментарий: 8k = 8192 байт; –

+0

thanx - исправлено - мы, выродки, должны быть аккуратно точными – Ray

+2

В чем разница между использованием Response.Write и написанием непосредственно объекта Response.OutputStream? – Odrade