На сайте ASP.net в моем месте работы следующий блок кода ответственен за обработку загрузок файла (ПРИМЕЧАНИЕ: Ответ. TransmitFile не используется здесь, потому что контент загрузки передается потоком из zip-файла):
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();
}
Наши пользователи часто загружают файлы на мультисотню МБ, которые могут уничтожить память сервера довольно быстро. Мое предположение - то, что это происходит из-за буферизации ответа. Это имеет смысл?
Я только что читал о 'буферном' свойстве объекта Ответа. Если я установил это на ложь, будет это предотвращать Ответ. BinaryWrite () звонит от буферизации данных в памяти? В целом, что хороший путь состоит в том, чтобы ограничить использование памяти в этой ситуации? Возможно, я должен передать потоком от zip до временного файла, затем назвать Ответ. TransmitFile ()?
Править: В дополнение к возможным решениям я очень интересуюсь объяснениями проблемы использования памяти, существующей в коде выше. Почему это использовало бы намного больше, чем 1 МБ, даже при том, что Ответ. Сброс называют на каждом повторении цикла? Это - просто ненужное выделение "кучи", которое происходит на каждом повторении цикла (и не получает GC'd сразу же), или есть ли что-то еще на работе?
Вот какой-то код, на котором я работаю для этого. Он использует 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();
}
Отредактировано, чтобы исправить синтаксическую ошибку и отсутствующее значение