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

A HTTP-ben az adatok POST-olásának két módja van: application/x-www-form-urlencoded és multipart/form-data. Úgy tudom, hogy a legtöbb böngésző csak a multipart/form-data használata esetén képes fájlokat feltölteni. Van további útmutatás arra vonatkozóan, hogy mikor kell valamelyik kódolási típust használni API-kontextusban (böngésző nélkül)? Ez például a következőkön alapulhat:

  • adatméret
  • nem ASCII karakterek létezése
  • (kódolatlan) bináris adatok megléte
  • további adatok (például fájlnév) átvitelének szükségessége.

A különböző tartalomtípusok használatára vonatkozóan eddig alapvetően nem találtam hivatalos útmutatást a weben.

Megoldás

TL;DR

Összefoglalva; ha bináris (nem alfanumerikus) adatokat (vagy jelentős méretű hasznos terhet) kell továbbítanod, használd a "multipart/form-data" opciót. Ellenkező esetben használd az application/x-www-form-urlencoded opciót.


Az Ön által említett MIME típusok a HTTP POST kérések két Content-Type fejlécét jelentik, amelyeket a felhasználói ügynököknek (böngészőknek) támogatniuk kell. Mindkét típusú kérés célja, hogy név/érték párok listáját küldje el a kiszolgálónak. A továbbítandó adatok típusától és mennyiségétől függően az egyik módszer hatékonyabb lesz, mint a másik. Ahhoz, hogy megértsük, miért, meg kell néznünk, mit csinálnak a fedő alatt.

Az application/x-www-form-urlencoded esetében a kiszolgálónak küldött HTTP-üzenet teste lényegében egy hatalmas lekérdezési karakterlánc - a név/érték párokat az írásjel (&) választja el, a neveket pedig az egyenlőségjel (=) választja el az értékektől. Egy példa erre: 

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

A specifikáció szerint:

[Fenntartott és] a nem alfanumerikus karakterek helyébe a karakter ASCII kódját jelző `%HH', egy százalékjel és két hexadecimális számjegy lép.

Ez azt jelenti, hogy minden egyes nem-alfanumerikus bájtra, amely az egyik értékünkben létezik, három bájtot kell használni a megjelenítéséhez. Nagy bináris fájlok esetén a hasznos adatmennyiség megháromszorozása rendkívül gazdaságtalan.

Itt jön a képbe a "multipart/form-data". A név/érték párok továbbításának ezen módszerével minden egyes pár egy MIME-üzenet "részeként" jelenik meg (ahogyan azt más válaszok leírják). A részeket egy adott karakterlánc határolja el egymástól (amelyet kifejezetten úgy választanak ki, hogy ez a határoló karakterlánc ne forduljon elő az "érték" hasznos töltetének egyikében sem). Minden egyes résznek saját MIME fejlécei vannak, mint például a Content-Type és különösen a Content-Disposition, amelyek minden résznek megadhatják a "nevét". Az egyes név/érték párok értékdarabja a MIME-üzenet egyes részeinek hasznos terhe. A MIME specifikáció több lehetőséget ad az érték hasznos terhének ábrázolásakor -- a sávszélesség megtakarítása érdekében választhatjuk a bináris adatok hatékonyabb kódolását (pl. 64-es bázis vagy akár nyers bináris).

Miért ne használhatnánk mindig a multipart/form-datat? Rövid alfanumerikus értékek esetén (mint a legtöbb webes űrlap) az összes MIME fejléc hozzáadásának többletköltsége jelentősen meghaladja a hatékonyabb bináris kódolásból származó megtakarításokat.

Kommentárok (16)

Nem hiszem, hogy a HTTP a POST-ra korlátozódik multipart vagy x-www-form-urlencoded esetén. A [Content-Type Header][1] ortogonális a HTTP POST módszerhez (kitöltheti a MIME-típust, amelyik megfelel). Ez a tipikus HTML-reprezentáción alapuló webalkalmazások esetében is így van (pl. a json payload nagyon népszerűvé vált az ajax-kérések payloadjának továbbítására).

A HTTP-n keresztüli Restful API-t illetően a legnépszerűbb tartalomtípusok, amelyekkel kapcsolatba kerültem, az application/xml és az application/json.

application/xml:

  • data-size: XML nagyon bőbeszédű, de általában nem probléma, ha tömörítést használunk, és arra gondolunk, hogy az írási hozzáférés esete (pl. POST vagy PUT révén) sokkal ritkább, mint az olvasási hozzáférés (sok esetben az összes forgalom
Kommentárok (3)

Sok mindennel egyetértek, amit Manuel mondott. Valójában a megjegyzései erre az url-re utalnak...

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

... amely kimondja:

A tartalom típusa "application/x-www-form-urlencoded" a következő nem hatékony a nagyméretű bináris adat- vagy szövegmennyiségek továbbítására nem ASCII karaktereket tartalmazó szöveg küldésére. A tartalomtípus "multipart/form-data" formanyomtatványok küldéséhez kell használni amelyek fájlokat, nem ASCII adatokat tartalmaznak, és bináris adatokat tartalmaznak.

Számomra azonban ez az eszköz/keretrendszer támogatásán múlik.

  • Milyen eszközöket és keretrendszereket az API felhasználóitól, hogy az API-felhasználók alkalmazásukat?
  • Van-e keretrendszerek vagy komponensek, amelyeket használhatnak amelyek előnyben részesítik az egyik módszert a a másik módszert előnyben részesítik?

Ha világos képet kap a felhasználókról, és arról, hogyan fogják használni az API-t, akkor ez segít a döntésben. Ha megnehezíti a fájlok feltöltését az API-felhasználók számára, akkor el fognak távolodni, és sok időt kell fordítania a támogatásukra.

Ehhez képest másodlagos lenne, hogy milyen eszköztámogatással rendelkezik az API megírásához, és hogy mennyire könnyű az Ön számára az egyik feltöltési mechanizmust a másikkal szemben alkalmaznia.

Kommentárok (2)