У HTTP існує два способи POST даних: application/x-www-form-urlencoded
і multipart/form-data
. Я розумію, що більшість браузерів можуть завантажувати файли, тільки якщо використовується multipart/form-data
. Чи є якісь додаткові вказівки, коли слід використовувати один з типів кодування в контексті API (без участі браузера)? Це може, наприклад, базуватися на
Наразі я не знайшов в Інтернеті жодних офіційних рекомендацій щодо використання різних типів контенту.
TL;DR
Підсумок; якщо вам потрібно передати двійкові (не алфавітно-цифрові) дані (або значне за розміром корисне навантаження), використовуйте multipart/form-data
. В іншому випадку використовуйте application/x-www-form-urlencoded
.
Згадані вами MIME-типи - це два заголовки Content-Type
для HTTP POST-запитів, які повинні підтримуватися користувацькими агентами (браузерами). Метою обох цих типів запитів є надсилання списку пар ім'я/значення на сервер. Залежно від типу та обсягу даних, що передаються, один з методів буде більш ефективним, ніж інший. Щоб зрозуміти чому, потрібно подивитися на те, що кожен з них робить "під ковдрою".
Для application/x-www-form-urlencoded
тіло HTTP-повідомлення, що відправляється на сервер, по суті є одним гігантським рядком запиту - пари ім'я/значення розділені амперсандом (&
), а імена відокремлюються від значень символом рівності (=
). Прикладом може бути:
МояЗміннаОдин=ЗначенняОдин&МояЗміннаДва=ЗначенняДва
Відповідно до специфікації:
[Reserved and] неалфавітно-цифрові символи замінюються на `%HH', знак відсотка та дві шістнадцяткові цифри, що представляють ASCII код символу
Це означає, що для кожного неалфавітно-цифрового байта, який існує в одному з наших значень, знадобиться три байти для його представлення. Для великих двійкових файлів потроєння корисного навантаження буде вкрай неефективним.
Ось тут і з'являється multipart/form-data
. При такому способі передачі пар ім'я/значення кожна пара представляється як &quo ;частина&quo ; в MIME-повідомленні (як описано в інших відповідях). Частини відокремлюються певною межею рядка (вибраною спеціально для того, щоб цей граничний рядок не зустрічався в жодному з &quo ;значень&quo ; корисного навантаження). Кожна частина має свій власний набір MIME-заголовків, таких як Content-Type
, і особливо Content-Disposition
, які можуть дати кожній частині її &quo ;ім'я.&quo ; Фрагмент значення кожної пари ім'я/значення є корисним навантаженням кожної частини MIME-повідомлення. Специфікація MIME надає нам більше можливостей при представленні корисного навантаження значення - ми можемо вибрати більш ефективне кодування двійкових даних для економії смуги пропускання (наприклад, база 64 або навіть сирий двійковий код).
Чому б не використовувати multipart/form-data
весь час? Для коротких алфавітно-цифрових значень (як у більшості веб-форм) накладні витрати на додавання всіх MIME-заголовків значно переважать будь-яку економію від більш ефективного двійкового кодування.
Я не думаю, що HTTP обмежується POST в багатокомпонентному або x-www-form-urlencoded. Заголовок Content-Type Header ортогональний методу HTTP POST (ви можете заповнити MIME-тип, який вам підходить). Це також стосується типових веб-додатків, заснованих на представленні HTML (наприклад, json став дуже популярним для передачі корисного навантаження для ajax-запитів).
Що стосується Restful API через HTTP, то найпопулярнішими типами контенту, з якими я стикався, є application/xml та application/json.
Я б спробував представити двійкові дані як власний актив/ресурс. Це додає ще один виклик, але краще розділяє дані. Приклади зображень:
;
POST /images
Content-type: multipart/mixed; boundary="xxxx"
... багатокомпонентні дані
201 Створено
Розташування: http://imageserver.org/../foo.jpg
;
У подальших ресурсах можна було просто вставляти бінарний ресурс як посилання:
;
;Багато з чим з того, що сказав Мануель, я згоден. Власне, в його коментарях є посилання на цей url...
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
... де сказано:
Тип контенту "application/x-www-form-urlencoded" є неефективний для відправки великих обсягів двійкових даних або тексту або тексту, що містить не-ASCII символи. Тип контенту Тип контенту &quo ;багатокомпонентні/форма-дані&quo ;; слід використовувати для відправки форм які містять файли, дані не в кодуванні ASCII, та двійкові дані.
Однак, як на мене, це зводилося б до підтримки інструменту/фреймворку.
Якщо ви отримаєте чітке уявлення про своїх користувачів і про те, як вони будуть використовувати ваш API, це допоможе вам прийняти рішення. Якщо ви ускладните завантаження файлів для користувачів вашого API, вони відійдуть, і ви витратите багато часу на їх підтримку.
Вторинним по відношенню до цього буде підтримка інструменту, який ви маєте для написання вашого API, і наскільки легко вам пристосувати один механізм завантаження до іншого.