Почему HttpPostedFile не работает так, как рекламируется и загружает данные на диск вместо буфера? - PullRequest
5 голосов
/ 18 июля 2009

Я загружаю большие файлы на сервер ASP.NET, используя стандартный элемент управления HTML <input> для публикации данных из нескольких частей. Это приложение ASP.NET MVC.

Согласно MSDN, класс HttpPostedFile буферизует на диск из коробки:

"Файлы загружаются в MIME формат multipart / form-data. От по умолчанию все запросы, включая форму поля и загруженные файлы, больше чем 256 КБ буферизуются на диск, а чем хранится в памяти сервера. "

Я предполагаю, что это означает, что когда я получаю доступ к HttpPostedFileBase в моем контроллере, то, когда я получаю доступ к свойству HttpPostedFileBase InputStream, я могу записать куда-нибудь файловый буфер, не беспокоясь о том, что сервер исчерпал память, которая, очевидно, является неработоспособным решением.

Вот немного псевдокода о том, как я обрабатываю каждый из входящих файлов из HttpPostedFileBase.

for(var i = 0; i< Request.Files.Count;i++)
{
    var fileBase = Request.Files[i];
    if (fileBase.ContentLength == 0)
    {
        continue;
    }

    // One thread per file
    ThreadPool.QueueUserWorkItem(state =>
    {
        // Read from fileBase.InputStream
    }, 
    null);
}

Блок httpRuntime моего web.config выглядит следующим образом:

<httpRuntime
  executionTimeout="1200"
  requestLengthDiskThreshold="2097151"
  maxRequestLength="2097151"
  useFullyQualifiedRedirectUrl="false"
  minFreeThreads="8"
  minLocalRequestFreeThreads="4"
  appRequestQueueLimit="100" />

Моя реализация работает, несколько файлов загружаются, как и ожидалось, за исключением того, что сервер использует все тот же объем памяти, который требуется для буферизации всей полезной нагрузки. Я должен предположить, что InputStream буферизует все. Когда я загружаю больше файлов, чем у меня есть память, он предсказуемо падает с OutOfMemoryException. Вот изображение всплеска памяти при загрузке файла 800 МБ.

alt text

Я знаю, что мог бы использовать виджет Flash / Silverlight или написать собственный HttpModule, чтобы перехватывать загрузки и обрабатывать их самостоятельно, но текущее требование будет работать безупречно, если HttpPostedFile сделает то, что MSDN говорит, что делает (или я делает это неправильно).

1 Ответ

5 голосов
/ 18 июля 2009

почему вы устанавливаете

requestLengthDiskThreshold="2097151"

в конфигурации? Разве это не заставляет сервер хранить все загрузки в оперативной памяти, а не буферизировать на диск?

...