application/x-www-form-urlencoded или multipart / form-data?
в HTTP есть два способа опубликовать данные:application/x-www-form-urlencoded
и multipart/form-data
. Я понимаю, что большинство браузеров могут загружать файлы только если есть. Есть ли какие-либо дополнительные рекомендации по использованию одного из типов кодировки в контексте API (без браузера)? Это может быть, например, основано на:
- размер данных
- существование символов, отличных от ASCII
- существование на (unencoded) двоичных данных
- необходимость передачи дополнительных данных (например, filename)
Я в основном не нашел официального руководства в интернете относительно использования различных типов контента до сих пор.
6 ответов
TL; DR
сводка; если у вас есть двоичные (не буквенно-цифровые) данные (или полезная нагрузка значительного размера) для передачи, используйте multipart/form-data
. В противном случае, используйте application/x-www-form-urlencoded
.
типы MIME, вы упоминаете два Content-Type
заголовки для запросов HTTP POST, которые должны поддерживать пользовательские агенты (браузеры). Целью обоих этих типов запросов является отправка на сервер списка пар имя / значение. В зависимости от типа и объема данных передается, один из методов будет более эффективным, чем другой. Чтобы понять, почему, вы должны посмотреть, что каждый делает под одеялом.
на application/x-www-form-urlencoded
, тело HTTP-сообщения, отправленного на сервер, по существу является одной гигантской строкой запроса - пары имя / значение разделены амперсандом (&
), а имена отделяются от значений символом equals (=
). Примером этого может служить:
MyVariableOne=ValueOne&MyVariableTwo=ValueTwo
по спецификация:
[зарезервированные и] не буквенно-цифровые символы заменяются на "%HH", знак процента и две шестнадцатеричные цифры, представляющие код ASCII символа
это означает, что для каждого не буквенно-цифрового байта, который существует в одном из наших значений, для его представления потребуется три байта. Для больших двоичных файлов утроение полезной нагрузки будет крайне неэффективным.
вот тут multipart/form-data
войти. С помощью этого метода передачи пар имя / значение каждая пара представлена как" часть " в сообщении MIME (как описано в других ответах). Части разделяются определенной Строковой границей (выбранной специально так, чтобы эта граничная строка не встречалась ни в одной из полезных нагрузок "значение"). Каждая часть имеет свой собственный набор заголовков MIME, как Content-Type
и особенно Content-Disposition
, который может дать каждой части свое "имя."Часть значения каждой пары имя / значение является полезной нагрузкой каждой части сообщение MIME. Спецификация MIME дает нам больше возможностей при представлении полезной нагрузки значения - мы можем выбрать более эффективное кодирование двоичных данных для сохранения полосы пропускания (например, base 64 или даже raw binary).
почему бы не использовать multipart/form-data
все время? Для коротких буквенно-цифровых значений (как и большинство веб-форм) накладные расходы на добавление всех заголовков MIME значительно перевешивают любую экономию от более эффективного двоичного кодирования.
ПРОЧИТАЙТЕ ХОТЯ БЫ ПЕРВЫЙ ПАРАГРАФ ЗДЕСЬ!
Я знаю, что это 3 года слишком поздно, но (принятый) ответ Мэтта неполон и в конечном итоге приведет вас к неприятностям. Ключ здесь в том, что, если вы решите использовать multipart/form-data
, границы должны не отображаются в файле данных, которые сервер в конечном итоге получает.
это не проблема для application/x-www-form-urlencoded
, потому что нет границы. x-www-form-urlencoded
может также всегда обрабатывать двоичные данные, простым целесообразность превращения одного произвольного байта в три 7BIT
байт. Неэффективно, но это работает (и обратите внимание, что комментарий о невозможности отправки имен файлов, а также двоичных данных неверен; вы просто отправляете его как другую пару ключ/значение).
проблема с multipart/form-data
заключается в том, что разделитель границ не должен присутствовать в данных файла (см. RFC2388; раздел 5.2 также включает довольно хромое оправдание отсутствия надлежащего агрегатного типа MIME, который позволяет избежать этого проблема.)
так, на первый взгляд, multipart/form-data
не имеет никакого значения в любой загрузка файлов, двоичных или других. Если вы неправильно выбираете границу, то вы будет в конце концов, есть проблема, отправляете ли вы обычный текст или необработанный двоичный файл - сервер найдет границу в неправильном месте, и ваш файл будет усечен, или сообщение потерпит неудачу.
ключ должен выбрать кодировку и границу, чтобы выбранный вами граничные символы не могут отображаться в закодированном выводе. Одно простое решение-использовать base64
(do не используйте RAW binary). В в base64 3 произвольных байта кодируются в четыре 7-битных символа, где выходной набор символов [A-Za-z0-9+/=]
(т. е. буквенно-цифровые, или '+', '/', '='). =
является частным случаем и может отображаться только в конце закодированного вывода, Как один =
или двойной ==
. Теперь выберите границу как 7-битную строку ASCII, которая не может появиться в base64
выход. Многие варианты, которые вы видите в сети, не проходят этот тест-MDN forms docs, например, использовать "blob" в качестве границы при отправке двоичных данных - нехорошо. Однако, что-то вроде "!капля!"никогда не появится в base64
выход.
Я не думаю, что HTTP ограничен публикацией в multipart или x-www-form-urlencoded. The Заголовок Типа Контента ортогонально методу HTTP POST (вы можете заполнить тип MIME, который вам подходит). Это также относится к типичным веб-приложениям на основе представления HTML (например, полезная нагрузка json стала очень популярной для передачи полезной нагрузки для запросов ajax).
относительно Restful API через HTTP самые популярные типы контента, с которыми я связался, - это application / xml и application / json.
application / xml:
- размер данных: XML очень подробный, но обычно не проблема при использовании сжатия и думать, что случай доступа для записи (например, через POST или PUT) гораздо реже, чем доступ для чтения (во многих случаях это
- существование символов, отличных от ascii: вы можете использовать utf-8 в качестве кодировки в XML
- существования бинарных данные: нужно будет использовать кодировку base64
- filename data: вы можете инкапсулировать это внутреннее поле в XML
application / json
- размер данных: более компактный меньше, чем XML, еще текст, но вы можете сжать
- non-ascii chars: json-utf-8
- двоичные данные: base64 (Также см. JSON-binary-вопрос)
- filename data: инкапсулировать как собственное поле-раздел внутри в JSON
двоичные данные как собственный ресурс
Я бы попытался представить двоичные данные как собственный актив / ресурс. Он добавляет еще один вызов, но развязывает материал лучше. Пример изображения:
POST /images
Content-type: multipart/mixed; boundary="xxxx"
... multipart data
201 Created
Location: http://imageserver.org/../foo.jpg
в более поздних ресурсах вы можете просто встроить двоичный ресурс как ссылку:
<main-resource>
...
<link href="http://imageserver.org/../foo.jpg"/>
</main-resource>
Я согласен со многим, что сказал Мануэль. Фактически, его комментарии ссылаются на этот url...
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
... который гласит:
тип содержимого "application/x-www-form-urlencoded" is неэффективно для отправки больших количество двоичных данных или текста содержит символы, отличные от ASCII. Этот тип контента " multipart / form-data" следует использовать для подачи форм что содержат файлы, не-ASCII данные, и двоичные данные.
однако для меня это сводится к поддержке инструмента / фреймворка.
- какие инструменты и механизмы вы ожидайте, что пользователи API будут создавать их приложения?
- у них есть рамки или компоненты, которые они могут использовать что за один способ за другие?
Если вы получите четкое представление о своих пользователях и о том, как они будут использовать ваш API, это поможет вам решать. Если вы затрудните загрузку файлов для пользователей API, они уйдут, и вы потратите много времени на их поддержку.
вторичным для этого будет поддержка инструмента, который у вас есть для написания вашего API, и как легко вам разместить один механизм загрузки над другим.
просто небольшой намек с моей стороны для загрузки данных HTML5 canvas image:
Я работаю над проектом для типографии и имел некоторые проблемы из-за загрузки изображений на сервер, который пришел из HTML5 canvas
элемент. Я боролся по крайней мере час, и я не получил его, чтобы сохранить изображение правильно на моем сервере.
как только я установлю
contentType
опция моего вызова jQuery ajax в application/x-www-form-urlencoded
все прошло правильно, и данные, закодированные в base64, были интерпретировано правильно и успешно сохранено как изображение.
может быть, это кому-то помогает!
Если вам нужно использовать Content-Type=x-www-urlencoded-form, то не используйте FormDataCollection в качестве параметра: In asp.net Core 2 + FormDataCollection не имеет конструкторов по умолчанию, которые требуются Форматерам. Вместо этого используйте IFormCollection:
public IActionResult Search([FromForm]IFormCollection type)
{
return Ok();
}