В HTTP има два начина за изпращане на данни: 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 съобщението, изпратено до сървъра, е по същество един огромен низ от заявки - двойките име/стойност са разделени с амперсанд (&
), а имената са отделени от стойностите със символа за равенство (=
). Пример за това е:
MyVariableOne=СтойностOne&MyVariableTwo=СтойностTwo
Според спецификацията:
[Запазени и] небуквените символи се заменят с `%HH', знак за процент и две шестнадесетични цифри, представляващи ASCII кода на символа
Това означава, че за всеки небуквен байт, който съществува в една от нашите стойности, ще са необходими три байта, за да бъде представен. За големи двоични файлове утрояването на полезния товар ще бъде крайно неефективно.
Ето къде се появява multipart/form-data
. При този метод за предаване на двойки име/стойност всяка двойка се представя като "part" в MIME съобщение (както е описано в други отговори). Частите се разделят с определен граничен низ (избран специално така, че този граничен низ да не се среща в нито един от полезните товари на "стойността"). Всяка част има свой собствен набор от MIME заглавия като Content-Type
и особено Content-Disposition
, които могат да дадат на всяка част нейното "име." Стойностната част на всяка двойка име/стойност е полезният товар на всяка част от MIME съобщението. Спецификацията на MIME ни дава повече възможности при представянето на полезния товар на стойността - можем да изберем по-ефективно кодиране на двоичните данни, за да спестим честотна лента (напр. база 64 или дори сурова двоица).
Защо да не използвате multipart/form-data
през цялото време? За кратки буквено-цифрови стойности (като повечето уеб формуляри) режийните разходи за добавяне на всички заглавия на MIME ще надхвърлят значително спестяванията от по-ефективно двоично кодиране.
Не мисля, че HTTP се ограничава до POST в мултипарт или x-www-form-urlencoded. Заглавието Content-Type Header е ортогонално на метода HTTP POST (можете да попълните MIME типа, който ви е подходящ). Такъв е случаят и с типичните уеб приложения, базирани на HTML представяне (напр. json payload стана много популярен за предаване на полезен товар за 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. В тип съдържание "multipart/form-data" трябва да се използва за изпращане на формуляри които съдържат файлове, данни, различни от ASCII, и двоични данни.
За мен обаче въпросът се свежда до поддръжката на инструменти/рамки.
Ако имате ясна представа за потребителите си и за това как те ще използват вашия API, това ще ви помогне да вземете решение. Ако затруднявате качването на файлове за потребителите на API, те ще се отдръпнат, а вие ще изразходвате много време, за да ги поддържате.
Второстепенно значение за това ще има поддръжката на инструментите, с които разполагате за писане на вашия API, и колко лесно е за вас да приспособите един механизъм за качване на файлове към друг.