application/x-www-form-urlencoded або multipart/form-data?

У HTTP існує два способи POST даних: application/x-www-form-urlencoded і multipart/form-data. Я розумію, що більшість браузерів можуть завантажувати файли, тільки якщо використовується multipart/form-data. Чи є якісь додаткові вказівки, коли слід використовувати один з типів кодування в контексті API (без участі браузера)? Це може, наприклад, базуватися на

  • розмір даних
  • наявність не-ASCII символів
  • наявність (некодованих) двійкових даних
  • необхідність передачі додаткових даних (наприклад, імені файлу)

Наразі я не знайшов в Інтернеті жодних офіційних рекомендацій щодо використання різних типів контенту.

Рішення

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-заголовків значно переважать будь-яку економію від більш ефективного двійкового кодування.

Коментарі (16)

Я не думаю, що HTTP обмежується POST в багатокомпонентному або x-www-form-urlencoded. Заголовок [Content-Type Header][1] ортогональний методу HTTP POST (ви можете заповнити MIME-тип, який вам підходить). Це також стосується типових веб-додатків, заснованих на представленні HTML (наприклад, json став дуже популярним для передачі корисного навантаження для ajax-запитів).

Що стосується Restful API через HTTP, то найпопулярнішими типами контенту, з якими я стикався, є application/xml та application/json.

application/xml:

  • data-size: XML дуже багатослівний, але зазвичай це не є проблемою, якщо використовувати стиснення і думати, що випадки доступу на запис (наприклад, через POST або PUT) набагато рідше, ніж доступ на читання (у багатьох випадках це
Коментарі (3)

Багато з чим з того, що сказав Мануель, я згоден. Власне, в його коментарях є посилання на цей 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, вони відійдуть, і ви витратите багато часу на їх підтримку.

Вторинним по відношенню до цього буде підтримка інструменту, який ви маєте для написання вашого API, і наскільки легко вам пристосувати один механізм завантаження до іншого.

Коментарі (2)