У меня есть API, состоящий из веб-сервисов ASP.NET, вызываемых через GET / POST / SOAP.
Новая функция потребует от меня принимать файлы через этот веб-сервис. По сути, я разрешаю пользователям загружать файлы в файловый архив через API, что в противном случае они бы сделали, войдя в нашу систему администрирования на основе браузера.
API должен использоваться как можно проще. Я подумываю отказаться от поддержки SOAP, поскольку наши клиенты PHP в основном используют методы GET / POST, а клиенты .NET не возражают. Имея это в качестве предварительного условия, я подумываю просто создать метод UploadFile (fileName) и потребовать, чтобы пользователь отправлял файл через POST как обычную загрузку файла.
Однако я не смогу указать поле файла в качестве параметра метода, верно? Итак, если я просто укажу в документации, что «файл должен быть отправлен в поле POST под названием« Файл »», возникнут ли какие-либо проблемы, когда мне нужно будет прочитать файл?
Все файлы в двоичном формате, PDF, различных форматах изображений, FLV и так далее. Кроме того, размеры файлов в основном будут около 2-20 МБ, но, учитывая приведенное выше решение, возникнут ли у меня проблемы с приемом файлов в области 250 МБ?
Получение файла таким образом приведет к тому, что файл будет полностью загружен в память, прежде чем я запишу его на диск - есть ли какой-либо способ обойти это, кроме разрешения службе получать поток и, таким образом, не позволять мне принимать другие параметры и препятствовать легкому использование сервиса?
Помимо того, что возможно с моей стороны, мне также любопытно, как я могу максимально упростить отправку файла вызываемым абонентам. Я предполагаю, что POST - один из наиболее доступных способов получить файл, но если у кого-то есть какие-либо комментарии, я бы тоже хотел их услышать.





"возникнут ли у меня проблемы, когда мне нужно будет прочитать файл?" Без проблем. Когда вы обрабатываете запрос POST, у вас есть вложение MIME к POST, которое является файлом. Прочитать этот файл относительно просто.
"Будут ли у меня проблемы с приемом файлов размером 250 МБ?" Нет. За исключением того, что для передачи больших файлов требуется некоторое время.
«Получение файла таким образом приведет к полной загрузке файла в память» Не обязательно верно. Многие веб-серверы обрабатывают запрос до вложения MIME и прекращают чтение, делая заголовки HTTP, запрос и открытый сокет доступными для дальнейшей обработки. Я не знаю об ASP, но знаю, что почти все фреймворки избегают чтения данных. Фреймворк оставляет это вашему приложению.
Следовательно, вы можете читать данные фрагментами и записывать (или обрабатывать) эти фрагменты, не считывая все данные в память.
POST - это именно то, как это делается. Есть не так много альтернатив, если не выйти за пределы узкого пространства веб-служб HTTP. Конечно, вы можете использовать другие протоколы, такие как FTP (TFTP, SFTP), для перемещения файлов, но это часто сбивает с толку людей, пишущих клиентские приложения.
При желании вы можете предоставить клиентскую библиотеку, которая создает объект HttpWebRequest с помощью метода POST и поток с вложением. Но вы не сильно сэкономите, потому что класс HttpWebRequest выглядит довольно просто. Вот образец кода.
Думаю, из входящего запроса можно создать поток. Примеры кода, которые я нашел, показывают, как по существу добавить поток к исходящему запросу.
Нет ничего ужасно плохого в наличии простого метода POST для отправки файла, просто детали привязки загрузки файла к любым подходящим метаданным (то есть другим параметрам метода, если они были связаны с методом).
Однако сегодня я считаю, что способ обработки больших объектов в вызовах SOAP - это MTOM. Это оптимизация, но она дает вам потоковый интерфейс для фактических полезных данных. Таким образом, фреймворк может при необходимости легко кэшировать большой объект на диск (действительно ли они это делают - другой вопрос, но никто не хочет поглощать 250-мегабайтную загрузку в память, поэтому я полагаю, что любой современный будет выгружать большие вложения) .
Я опасаюсь, что переход на SOAP / MTOM / InputStream отпугнет наших неуправляемых клиентов, поскольку им будет очень сложно пользоваться нашими услугами.
В конце концов, SOAP - это формат XML. Формат MTOM (должен быть) прост. Вы можете создавать служебные функции с единственной целью - вызвать службу, даже если вы создаете пакет MTOM «вручную». Просто нужно сделать это один раз и отдать своим клиентам. Нет необходимости в инструментарии.
Не прямой ответ, но вы также можете посмотреть BITS - фоновая интеллектуальная служба передачи [wiki]
Это может иметь или не иметь отношения к вам / вашим клиентам.
However, I will not be able to specify the file field as a parameter to the method, right? So if I simply state in the documentation "file should be sent in POST field called 'File'", would that pose any problems when I need to read the file?
Нет причин, по которым вы не можете включить дополнительные параметры POST (или GET, если на то пошло). Я бы, вероятно, сам взял имя файла в качестве дополнительного параметра POST, чтобы клиенты, которые автоматически используют локальное имя файла в запросе, могли легко переименовать. Если я ожидал конфликтов имен, я мог бы даже вернуть выбранное имя сервера в случае конфликтов ... Я думаю, что ребята из REST используют для этого какой-то код статуса HTTP Created.
All files are in binary format, PDF's, various image formats, FLV and so forth. Also, file sizes will mainly be in the 2-20MB vicinity, but given the above solution, would I have any troubles accepting files in the 250MB area?
Вам нужно будет настроить maxRequestLengths и executionTimeouts в web.config. И, если кто-то попытается загрузить 250 МБ по коммутируемому соединению - ну, скажем так, это, вероятно, не сработает.
Receiving a file this way would result in the file being loaded completely into memory, before I write it to disk - is there any way around this, besides letting the service receive a Stream and thus disabling me from accepting other parameters, and hindering the easy usage of the service?
ASP.NET 2.0+ буферизует загруженные файлы на диск по мере их поступления, чтобы избежать предварительной загрузки всего запроса в ОЗУ. Настройте requestLengthDiskThreshold web.config, чтобы сбалансировать скорость и использование памяти. Вы не могли бы взять Stream, если бы захотели ... хотя вы могли бы принять массив byte []. Я действительно не уверен, что это могло значить ...
Для небольших файлов вы можете использовать base 64, что должно быть тривиально для клиентов. Но для 20 МБ накладные расходы того не стоят.
Существует множество различных компонентов загрузки файлов ASP.NET, которые в основном подключаются к Begin_Request как HttpModule и перехватывают поток запросов для любых загрузок multippart / form. С ASP.NET 2.0 в этом, вероятно, нет необходимости, если только вы не хотите обеспечить какой-то обратный вызов прогресса или что-то в этом роде. Если это так - их механика должна работать с веб-сервисом одинаково.
RFC 1867 является соответствующей спецификацией, но этот компонент загрузки хорошо описывает, как выглядит запрос, если вы намереваетесь проанализировать свой собственный.
Единственный вопросительный знак, который у меня был бы, это каков уровень поддержки multipart / form-data в http-библиотеках ваших клиентов. Я подозреваю, что все вокруг довольно хорошо, но вы можете проверить.
Я почти уверен, что ASP.NET также считывает вложения в память, но вы заставили меня усомниться - мне придется это проверить. Чтение его по частям будет возможно только в том случае, если я либо приму поток, либо полностью проигнорирую способ веб-службы и прочитаю входной поток напрямую, как мне кажется.