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

In HTTP zijn er twee manieren om gegevens te POST-en: application/x-www-form-urlencoded en multipart/form-data. Ik heb begrepen dat de meeste browsers alleen bestanden kunnen uploaden als multipart/form-data wordt gebruikt. Zijn er aanvullende richtlijnen voor het gebruik van een van de coderingstypes in een API context (zonder browser)? Dit zou bijvoorbeeld gebaseerd kunnen zijn op:

  • gegevensgrootte
  • het bestaan van niet-ASCII-tekens
  • het bestaan van (niet-gecodeerde) binaire gegevens
  • de noodzaak om extra gegevens (zoals bestandsnaam) over te dragen

Tot nu toe heb ik op het web geen formele richtsnoeren gevonden voor het gebruik van de verschillende inhoudstypen.

Oplossing

TL;DR

Samenvatting; als je binaire (niet-alfanumerieke) data (of een payload van aanzienlijke grootte) wilt verzenden, gebruik dan multipart/form-data. Anders, gebruik application/x-www-form-urlencoded.


De MIME types die je noemt zijn de twee Content-Type headers voor HTTP POST requests die user-agents (browsers) moeten ondersteunen. Het doel van beide soorten verzoeken is om een lijst van naam/waarde paren naar de server te sturen. Afhankelijk van het type en de hoeveelheid gegevens die worden verzonden, zal een van de methoden efficiënter zijn dan de andere. Om te begrijpen waarom, moet je kijken naar wat beide onder de dekmantel doen.

Voor application/x-www-form-urlencoded, is de body van het HTTP bericht dat naar de server wordt gestuurd in wezen één grote query string -- naam/waarde paren worden gescheiden door de ampersand (&), en namen worden van waarden gescheiden door het gelijk-teken (=). Een voorbeeld hiervan zou zijn: 

MijnVariabeleEén=WaardeEén&MijnVariabeleTwee=WaardeTwee.

Volgens de [specificatie] (http://www.w3.org/TR/html401/interact/forms.html):

[Gereserveerde en] niet-alfanumerieke tekens worden vervangen door `%HH', een procentteken en twee hexadecimale cijfers die de ASCII-code van het teken weergeven

Dat betekent dat voor elke niet-alfanumerieke byte in een van onze waarden, er drie bytes nodig zijn om die weer te geven. Voor grote binaire bestanden zal het verdrievoudigen van de payload zeer inefficiënt zijn.

Dat is waar multipart/form-data om de hoek komt kijken. Met deze methode voor het verzenden van naam/waarde paren, wordt elk paar weergegeven als een "part" in een MIME bericht (zoals beschreven in andere antwoorden). De delen worden gescheiden door een bepaalde stringgrens (speciaal zo gekozen dat deze grensstring niet voorkomt in een van de "value" payloads). Elk deel heeft zijn eigen set MIME headers zoals Content-Type, en in het bijzonder Content-Disposition, die elk deel zijn "name." Het waarde deel van elk naam/waarde paar is de payload van elk deel van het MIME bericht. De MIME spec geeft ons meer opties bij het weergeven van de waarde payload -- we kunnen een efficiëntere codering van binaire gegevens kiezen om bandbreedte te besparen (b.v. base 64 of zelfs raw binary).

Waarom niet altijd multipart/form-data gebruiken? Voor korte alfanumerieke waarden (zoals de meeste webformulieren) zal de overhead van het toevoegen van alle MIME headers veel groter zijn dan de besparing van een efficiëntere binaire codering.

Commentaren (16)

Ik denk niet'dat HTTP beperkt is tot POST in multipart of x-www-form-urlencoded. De [Content-Type Header][1] is orthogonaal aan de HTTP POST methode (je kunt MIME type invullen dat bij je past). Dit is ook het geval voor typische HTML representatie gebaseerde webapps (bv. json payload werd zeer populair voor het verzenden van payload voor ajax verzoeken).

Wat betreft Restful API over HTTP zijn de meest populaire content-types waar ik mee in aanraking ben gekomen application/xml en application/json.

application/xml:

  • data-grootte: XML zeer verbose, maar meestal geen probleem bij gebruik van compressie en denken dat de write-access geval (bijvoorbeeld via POST of PUT) is veel zeldzamer als read-access (in veel gevallen is het
Commentaren (3)

Ik ben het eens met veel van wat Manuel heeft gezegd. In feite, zijn opmerkingen verwijzen naar deze url...

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

... waarin staat:

Het inhoudstype "application/x-www-form-urlencoded" is inefficiënt voor het verzenden van grote hoeveelheden binaire data of tekst die niet-ASCII tekens bevat. De content type "multipart/form-data" moet worden gebruikt voor het verzenden van formulieren die bestanden, niet-ASCII gegevens bevatten, en binaire data.

Voor mij zou het echter neerkomen op tool/framework ondersteuning.

  • Welke tools en frameworks verwacht je verwacht je dat je API gebruikers hun hun apps met?
  • Hebben zij frameworks of componenten die ze kunnen gebruiken die de ene methode prefereren boven de de andere?

Als je een duidelijk beeld krijgt van je gebruikers, en hoe zij'gebruik zullen maken van je API, dan zal dat je helpen beslissen. Als u het uploaden van bestanden moeilijk maakt voor uw API-gebruikers dan zullen zij'weggaan, of u'zult veel tijd besteden aan het ondersteunen van hen.

Secundair aan dit zou zijn de tool ondersteuning JIJ hebt voor het schrijven van uw API en hoe gemakkelijk het is voor uw om een upload mechanisme tegemoet te komen over de andere.

Commentaren (2)