Как загрузить большие (> 25 МБ) файлы в веб-сервис?
У меня есть веб-сервис, который берет байт [] и сохраняет его.
Это прекрасно работает для "маленьких" файлов, но как только я достиг определенного размера, веб-служба перестает работать и возвращает "Запрос не выполнен с HTTP-статусом 404: Не найдено".
Из того, что я видел, похоже, что это настройка IIS, ограничивающая размер файла, который можно публиковать (чтобы предотвратить атаки типа "отказ в обслуживании"). Я пытался увеличить этот параметр, но у меня возникают проблемы с определением, какой параметр и где / как можно установить. Я использую IIS7 и веб-сервис сделан в.net (asmx).
В файле web.config веб-службы я добавил следующее (что, как представляется, увеличивает размер файла, который может быть принят, но не полностью до этого размера параметра)
<system.web>
<httpRuntime executionTimeout="999999" maxRequestLength="2097151" />
...
</system.web>
Любые предложения о том, где (и как) увеличить размер файла, что веб-сервис будет принята с благодарностью.
8 ответов
В дополнение к httpRuntime/maxRequestLength, упомянутому в вопросе, похоже, что есть дополнительный элемент, который можно добавить в файл web.config веб-службы, чтобы разрешить передачу больших файлов.
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2000000000" />
</requestFiltering>
</security>
</system.webServer>
Это позволяет загружать файлы большего размера через веб-сервисы.
Следует помнить, что веб-сервисы не предназначены в первую очередь как механизмы передачи файлов. Любой специально разработанный протокол передачи файлов, вероятно, будет работать лучше, чем веб-сервис. Например, такие протоколы с большей вероятностью будут иметь дело с восстановлением после ошибок, частичной загрузкой и т. Д.
Однако, если вы собираетесь использовать для этого веб-сервисы в.NET, вы должны использовать WCF, если это вообще возможно. Среди прочих преимуществ WCF поддерживает потоковую передачу и, следовательно, будет намного более эффективным с точки зрения использования памяти. Я обеспокоен тем, что если вы последуете двум (точным) предложениям, приведенным выше, ваш следующий результат будет исключением "нехватка памяти или ресурсов", так как старая технология ASMX пытается загрузить весь ваш файл размером 25 МБ в память сразу. На самом деле, он может иметь несколько копий в памяти одновременно!
Если бы я застрял с необходимостью использовать веб-сервисы и нуждался в поддержке очень больших файлов, я бы посмотрел на реализацию системы, которая позволяет загружать файлы по частям.
Например.
- ticketId GetTicket (размер)
- UploadData (ticketId, byte [] payload) (может вызываться столько раз, сколько вы хотите)
- FinalizeUpload (TicketID)
Это позволит вам распределять большие загрузки и не хранить слишком много данных в памяти. Недостатком является то, что вы все еще используете довольно неэффективный транспортный механизм.
Просто чтобы добавить информацию людям, прибегающим к помощи этого web.config:
C: \ Program Files \ Common Files \ Microsoft Shared \ Расширения веб-сервера \12\ISAPI
<location path="Copy.asmx"> <!-- Name of you asmx -->
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="104857600"/> <!-- 100 megs -->
</requestFiltering>
</security>
</system.webServer>
</location>
Это решило нашу проблему после устранения этой проблемы в течение довольно сомнительного времени.
Если вы настроены на использование веб-служб для перемещения по файлам, я бы по крайней мере рассмотрел возможность использования вложений WS-Attachment / DIME. Основная проблема при отправке byte[] через веб-сервисы заключается в том, что они помещаются в тело SOAP, которое кодируется в виде базовой строки 64. Подобное кодирование файлов увеличивает размер файла на целых две трети в мыльном теле (т. Е. Файл размером 6 МБ становится файлом 9 МБ по сети).
Вероятно, ваша загрузка 25 МБ превращается в ОГРОМНЫЕ мыльные конверты.
Я настоятельно рекомендую прочитать это. Что может привести вас в DIME.
Вот выдержка.
WSE Toolkit от Microsoft позволяет отправлять большие вложения вместе с методом веб-службы с использованием стандартов DIME и WS-Attachments. Мы рассмотрим эти стандарты и выясним, почему они более эффективны, чем отправка больших объемов двоичных данных в вызове веб-службы другими распространенными способами.
Надеюсь, это поможет!
Значение maxRequestLength указывается в килобайтах, а не в байтах. Это должно дать вам ограничение 30 МБ в течение 4-минутного периода ожидания.
<httpRuntime executionTimeout="240" maxRequestLength="30000" />
Слишком большое число может фактически помешать применению ваших значений. Я думаю, что столкнулся с этим несколько лет назад, когда я думал, что это был предел байтов (смутная память).
Это не дает конкретного ответа на ваш вопрос, но в прошлом я использовал WCF для передачи имен файлов / путей / списков, а затем использовал библиотеку FTP для передачи файлов по FTP.
Это сработало для меня:
<binding name="uploadFilesBasicHttpBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:10:10" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>