application/x-www-form-urlencoded alebo multipart/form-data?

V protokole HTTP existujú dva spôsoby odosielania údajov POST: application/x-www-form-urlencoded a multipart/form-data. Chápem, že väčšina prehliadačov dokáže odosielať súbory len vtedy, ak sa použije multipart/form-data. Existuje nejaký ďalší návod, kedy použiť jeden z typov kódovania v kontexte API (bez zapojenia prehliadača)? Mohlo by to byť založené napr:

  • veľkosti údajov
  • existencii znakov iných ako ASCII
  • existencia (nekódovaných) binárnych údajov
  • potrebe prenosu ďalších údajov (ako je názov súboru)

Na webe som zatiaľ v podstate nenašiel žiadne formálne usmernenie týkajúce sa používania rôznych typov obsahu.

Riešenie

TL;DR

Zhrnutie; ak chcete prenášať binárne (nealfanumerické) údaje (alebo značne veľké užitočné zaťaženie), použite multipart/form-data. V opačnom prípade použite application/x-www-form-urlencoded.


Typy MIME, ktoré spomínate, sú dve hlavičky Content-Type pre požiadavky HTTP POST, ktoré musia podporovať používateľskí agenti (prehliadače). Účelom oboch týchto typov požiadaviek je odoslať serveru zoznam párov meno/hodnota. V závislosti od typu a množstva prenášaných údajov bude jedna z metód efektívnejšia ako druhá. Aby ste pochopili prečo, musíte sa pozrieť na to, čo každá z nich robí pod pokrievkou.

V prípade metódy application/x-www-form-urlencoded je telo správy HTTP odosielanej serveru v podstate jeden obrovský reťazec dopytu - dvojice meno/hodnota sú oddelené ampersandom (&) a mená sú od hodnôt oddelené symbolom rovnosti (=). Príkladom môže byť: 

MyVariableOne=HodnotaOne&MyVariableTwo=HodnotaTwo

Podľa špecifikácie:

Nealfanumerické znaky sú nahradené znakom `%HH', znakom percenta a dvoma hexadecimálnymi číslicami, ktoré predstavujú ASCII kód znaku

To znamená, že pre každý nealfanumerický bajt, ktorý existuje v jednej z našich hodnôt, budú potrebné tri bajty na jeho reprezentáciu. Pri veľkých binárnych súboroch bude trojnásobné zaťaženie veľmi neefektívne.

Preto prichádza na rad multipart/form-data. Pri tomto spôsobe prenosu párov názov/hodnota je každý pár reprezentovaný ako "part" v správe MIME (ako je popísané v iných odpovediach). Časti sú oddelené určitým ohraničujúcim reťazcom (vybraným špeciálne tak, aby sa tento ohraničujúci reťazec nevyskytoval v žiadnom z "hodnotových" užitočných zaťažení). Každá časť má svoju vlastnú sadu hlavičiek MIME, ako napríklad Content-Type, a najmä Content-Disposition, ktoré môžu každej časti dať jej "meno." Hodnotová časť každého páru meno/hodnota je užitočné zaťaženie každej časti správy MIME. Špecifikácia MIME nám dáva viac možností pri reprezentácii hodnotového užitočného zaťaženia -- môžeme si vybrať efektívnejšie kódovanie binárnych údajov, aby sme ušetrili šírku pásma (napr. base 64 alebo dokonca raw binary).

Prečo nepoužívať multipart/form-data stále? V prípade krátkych alfanumerických hodnôt (ako je väčšina webových formulárov) bude réžia pridávania všetkých hlavičiek MIME výrazne prevyšovať akékoľvek úspory z efektívnejšieho binárneho kódovania.

Komentáre (16)

Nemyslím si, že HTTP je obmedzený na POST v multipart alebo x-www-form-urlencoded. Hlavička [Content-Type][1] je ortogonálna k metóde HTTP POST (môžete vyplniť typ MIME, ktorý vám vyhovuje). To je aj prípad typických webových aplikácií založených na reprezentácii HTML (napr. json payload sa stal veľmi populárnym na prenos užitočného zaťaženia pre ajaxové požiadavky).

Pokiaľ ide o Restful API cez HTTP, najpopulárnejšie typy obsahu, s ktorými som prišiel do styku, sú application/xml a application/json.

application/xml:

  • data-size: XML veľmi slovné, ale zvyčajne to nie je problém, ak používame kompresiu a myslíme na to, že prípad prístupu na zápis (napr. prostredníctvom POST alebo PUT) je oveľa zriedkavejší ako prístup na čítanie (v mnohých prípadoch tvorí
Komentáre (3)

Súhlasím s mnohým, čo Manuel povedal. V skutočnosti sa jeho pripomienky týkajú tejto url adresy...

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

... kde sa uvádza:

Typ obsahu "application/x-www-form-urlencoded" je neefektívny na odosielanie veľkých množstva binárnych údajov alebo textu obsahujúce znaky iné ako ASCII. Na stránke typ obsahu "multipart/form-data" by sa mal používať na odosielanie formulárov ktoré obsahujú súbory s údajmi, ktoré nie sú v tvare ASCII, a binárne údaje.

Podľa mňa by však záležalo na podpore nástrojov/frameworkov.

  • Aké nástroje a rámce používate očakávate, že vaši používatelia API budú vytvárať svoje aplikácie?
  • Majú rámce alebo komponenty, ktoré môžu používať ktoré uprednostňujú jednu metódu pred druhou. druhú?

Ak máte jasnú predstavu o svojich používateľoch a o tom, ako budú využívať vaše API, pomôže vám to pri rozhodovaní. Ak používateľom vášho API sťažíte nahrávanie súborov, potom sa od vás vzdialia a vy strávite veľa času ich podporou.

Sekundárnou otázkou bude podpora nástrojov, ktoré máte k dispozícii na písanie vášho API, a to, ako ľahko sa prispôsobíte jednému mechanizmu nahrávania oproti druhému.

Komentáre (2)