Как доставить большие файлы в ASP.NET Response?
Я не ищу какой-либо альтернативы для потоковой передачи содержимого файла из базы данных, на самом деле я ищу корень проблемы, это был файл до IIS 6, где мы запускали наше приложение в классическом режиме, теперь мы обновили IIS до 7, и мы запуск пула приложений в конвейерном режиме, и эта проблема началась.
У меня есть обработчик, где я должен доставлять большие файлы по запросу клиента. И я сталкиваюсь со следующими проблемами,
Файлы имеют средний размер от 4 до 100 МБ, поэтому давайте рассмотрим случай загрузки файлов размером 80 МБ.
Буферизация включена, медленный старт
Response.BufferOutput = True;
Это приводит к очень медленному запуску файла, поскольку пользовательские загрузки и даже индикатор выполнения не появляются в течение нескольких секунд, обычно от 3 до 20 секунд, причина в том, что IIS сначала читает весь файл, определяет длину содержимого, а затем начинает передачу файла , Файл воспроизводится в видеоплеере и работает очень медленно, однако iPad сначала загружает только часть файла, поэтому он работает быстро.
Отключение буферизации, отсутствие длины контента, быстрый запуск, отсутствие прогресса
Reponse.BufferOutput = False;
Это приводит к немедленному запуску, однако конечный клиент (типичный браузер, такой как Chrome) не знает Content-Length, поскольку IIS тоже не знает, поэтому он не отображает ход выполнения, вместо этого он сообщает, что загружено X KB.
Отключение буферизации, длина содержимого вручную, быстрый запуск, выполнение и нарушение протокола
Response.BufferOutput = False;
Response.AddHeader("Content-Length", file.Length);
Это приводит к правильной немедленной загрузке файлов в Chrome и т. Д., Однако в некоторых случаях обработчик IIS приводит к ошибке «Закрытое подключение удаленного клиента» (это очень часто), а другие WebClient приводят к нарушению протокола.Это происходит от 5 до 10% всех запросов, а не каждый запрос.
Я предполагаю, что происходит, IIS не отправляет ничего, что называется 100 continue, когда мы не выполняем буферизацию, и клиент может отключиться, не ожидая какого-либо вывода. Тем не менее, чтение файлов из источника может занять больше времени, но на стороне клиента я увеличил время ожидания, но похоже на время ожидания IIS и не могу контролировать.
Могу ли я в любом случае принудительно заставить Response отправить 100 и продолжить, чтобы никто не закрыл соединение?
ОБНОВИТЬ
В Firefox / Chrome я обнаружил следующие заголовки, здесь нет ничего необычного для нарушения протокола или плохого заголовка.
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:POST, GET, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000
Cache-Control:private
Content-Disposition:attachment; filename="24.jpg"
Content-Length:22355
Content-Type:image/pjpeg
Date:Wed, 07 Mar 2012 13:40:26 GMT
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
ОБНОВЛЕНИЕ 2
Включение Recycling все еще не принесло больших результатов, но я увеличил свой MaxWorkerProcess до 8, и теперь я получаю меньше ошибок, чем раньше.
Но в среднем из 200 запросов в секунду от 2 до 10 запросов завершаются неудачно ... и это происходит почти каждые две секунды.
ОБНОВЛЕНИЕ 3
Продолжая 5% запросов с ошибкой "Сервер совершил нарушение протокола. Section = ResponseStatusLine", у меня есть другая программа, которая загружает контент с веб-сервера, который использует WebClient, и который выдает эту ошибку 4-5 раз в секунду, в среднем я 5% запросов не выполняются. Есть ли способ отследить сбой WebClient?
Переопределенные проблемы
Получен нулевой байт файл
IIS по какой-то причине закрывает соединение, на стороне клиента в WebConfig я получаю 0 байт для файла, который не является нулевым байтом, мы выполняем проверку хэша SHA1, это говорит нам о том, что на веб-сервере IIS ошибка не записывается.
Это была моя ошибка, и она была решена, так как мы использовали Entity Framework, она считывала грязные (незафиксированные строки), так как считывание не было в области транзакции, а помещение в область транзакции решило эту проблему.
Возникло исключение нарушения протокола
WebClient выдает WebException, говоря: «Сервер совершил нарушение протокола. Section = ResponseStatusLine.
Я знаю, что могу включить небезопасный разбор заголовков, но это не главное, когда мой HTTP-обработчик отправляет правильные заголовки, не знаю, почему IIS отправляет что-то лишнее (проверено на firefox и chrome, ничего необычного), это происходит только 2 % раз.
ОБНОВЛЕНИЕ 4
Нашел ошибку sc-win32 64 и где-то читал, что WebLimits для MinBytesPerSecond нужно изменить с 240 на 0, все равно все так же. Однако я заметил, что всякий раз, когда IIS регистрирует ошибку 64 sc-win32, IIS записывает HTTP Status как 200, но при этом возникает некоторая ошибка. Теперь я не могу включить Failed Trace Logging для 200, потому что это приведет к массивным файлам.
Обе вышеперечисленные проблемы были решены путем увеличения MinBytesPerSecond, а также путем отключения сеансов, я добавил подробный ответ, суммирующий каждую точку.