application/x-www-form-urlencoded или multipart/form-data?

В HTTP има два начина за изпращане на данни: 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 съобщението, изпратено до сървъра, е по същество един огромен низ от заявки - двойките име/стойност са разделени с амперсанд (&), а имената са отделени от стойностите със символа за равенство (=). Пример за това е: 

MyVariableOne=СтойностOne&MyVariableTwo=СтойностTwo

Според спецификацията:

[Запазени и] небуквените символи се заменят с `%HH', знак за процент и две шестнадесетични цифри, представляващи ASCII кода на символа

Това означава, че за всеки небуквен байт, който съществува в една от нашите стойности, ще са необходими три байта, за да бъде представен. За големи двоични файлове утрояването на полезния товар ще бъде крайно неефективно.

Ето къде се появява multipart/form-data. При този метод за предаване на двойки име/стойност всяка двойка се представя като "part" в MIME съобщение (както е описано в други отговори). Частите се разделят с определен граничен низ (избран специално така, че този граничен низ да не се среща в нито един от полезните товари на "стойността"). Всяка част има свой собствен набор от MIME заглавия като Content-Type и особено Content-Disposition, които могат да дадат на всяка част нейното "име." Стойностната част на всяка двойка име/стойност е полезният товар на всяка част от MIME съобщението. Спецификацията на MIME ни дава повече възможности при представянето на полезния товар на стойността - можем да изберем по-ефективно кодиране на двоичните данни, за да спестим честотна лента (напр. база 64 или дори сурова двоица).

Защо да не използвате multipart/form-data през цялото време? За кратки буквено-цифрови стойности (като повечето уеб формуляри) режийните разходи за добавяне на всички заглавия на MIME ще надхвърлят значително спестяванията от по-ефективно двоично кодиране.

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

Не мисля, че HTTP се ограничава до POST в мултипарт или x-www-form-urlencoded. Заглавието [Content-Type Header][1] е ортогонално на метода HTTP POST (можете да попълните MIME типа, който ви е подходящ). Такъв е случаят и с типичните уеб приложения, базирани на HTML представяне (напр. json payload стана много популярен за предаване на полезен товар за 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. В тип съдържание "multipart/form-data" трябва да се използва за изпращане на формуляри които съдържат файлове, данни, различни от ASCII, и двоични данни.

За мен обаче въпросът се свежда до поддръжката на инструменти/рамки.

  • Какви инструменти и рамки използвате очаквате потребителите на вашия API да изграждат своите приложения?
  • Имат ли те рамки или компоненти, които могат да използват които предпочитат един метод пред друг. другия?

Ако имате ясна представа за потребителите си и за това как те ще използват вашия API, това ще ви помогне да вземете решение. Ако затруднявате качването на файлове за потребителите на API, те ще се отдръпнат, а вие ще изразходвате много време, за да ги поддържате.

Второстепенно значение за това ще има поддръжката на инструментите, с които разполагате за писане на вашия API, и колко лесно е за вас да приспособите един механизъм за качване на файлове към друг.

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