Frage application / x-www-form-urlencoded oder multipart / form-data?


In HTTP gibt es zwei Möglichkeiten für POST-Daten: application/x-www-form-urlencoded und multipart/form-data. Ich verstehe, dass die meisten Browser nur Dateien hochladen können, wenn multipart/form-data wird eingesetzt. Gibt es eine zusätzliche Anleitung, wenn einer der Kodierungstypen in einem API-Kontext verwendet werden soll (kein Browser beteiligt)? Dies könnte z.B. basiert auf:

  • Datengröße
  • Vorhandensein von Nicht-ASCII-Zeichen
  • Existenz auf (uncodierten) Binärdaten
  • die Notwendigkeit, zusätzliche Daten (wie Dateiname) zu übertragen

Ich habe im Internet keine formelle Anleitung zur Verwendung der verschiedenen Inhaltstypen gefunden.


1066
2017-10-24 11:12


Ursprung


Antworten:


TL; DR

Zusammenfassung; Wenn Sie binäre (nicht-alphanumerische) Daten (oder Nutzdaten mit einer signifikanten Größe) übertragen möchten, verwenden Sie multipart/form-data. Ansonsten, verwenden Sie application/x-www-form-urlencoded.


Die MIME-Typen, die Sie erwähnen, sind die beiden Content-Type Header für HTTP-POST-Anfragen, die Benutzeragenten (Browser) unterstützen müssen. Der Zweck dieser beiden Arten von Anforderungen besteht darin, eine Liste von Name / Wert-Paaren an den Server zu senden. Je nach Art und Menge der übertragenen Daten ist eine der Methoden effizienter als die andere. Um zu verstehen, warum, müssen Sie schauen, was jeder unter den Abdeckungen tut.

Zum application/x-www-form-urlencoded, der Hauptteil der HTTP-Nachricht, die an den Server gesendet wird, ist im Wesentlichen eine riesige Abfragezeichenfolge - Name / Wert-Paare sind durch das kaufmännische Und getrennt (&), und Namen werden von Werten durch das Gleichheitszeichen getrennt (=). Ein Beispiel dafür wäre:

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

Entsprechend der Spezifikation:

[Reservierte und] nicht alphanumerische Zeichen werden durch "% HH" ersetzt, ein Prozentzeichen und zwei Hexadezimalziffern, die den ASCII-Code des Zeichens darstellen

Das bedeutet, dass für jedes nicht-alphanumerische Byte, das in einem unserer Werte existiert, es drei Bytes benötigt, um es darzustellen. Bei großen binären Dateien wird eine Verdreifachung der Nutzlast sehr ineffizient sein.

Das ist wo multipart/form-data kommt herein. Bei dieser Methode der Übertragung von Name / Wert-Paaren wird jedes Paar als "Teil" in einer MIME-Nachricht dargestellt (wie von anderen Antworten beschrieben). Teile werden durch eine bestimmte Zeichenfolgenbegrenzung getrennt (die speziell dafür ausgewählt wird, dass diese Begrenzungszeichenfolge in keiner der Nutzdaten mit "Wert" auftritt). Jeder Teil hat seine eigenen MIME-Header wie Content-Typeund besonders Content-Disposition, die jedem Teil seinen "Namen" geben kann. Der Wert eines jeden Name / Wert-Paares ist die Nutzlast jedes Teils der MIME-Nachricht. Die MIME-Spezifikation gibt uns mehr Optionen, wenn wir die Nutzlast darstellen - wir können eine effizientere Codierung von Binärdaten wählen, um Bandbreite zu sparen (z.B. Basis 64 oder sogar Rohbinär).

Warum nicht benutzen? multipart/form-data die ganze Zeit? Bei kurzen alphanumerischen Werten (wie bei den meisten Webformularen) wird der Overhead beim Hinzufügen aller MIME-Header die Einsparungen durch effizientere Binärcodierung deutlich überwiegen.


1666
2017-11-01 21:59



LESEN SIE MINDESTENS DAS ERSTE PARA HIER!

Ich weiß, dass das 3 Jahre zu spät ist, aber Matts (akzeptierte) Antwort ist unvollständig und wird dich schließlich in Schwierigkeiten bringen. Der Schlüssel hier ist, dass, wenn Sie sich entscheiden zu verwenden multipart/form-data, muss die Grenze sein nicht erscheinen in den Dateidaten, die der Server schließlich erhält.

Dies ist kein Problem für application/x-www-form-urlencodedweil es keine Grenze gibt. x-www-form-urlencoded kann auch immer mit binären Daten umgehen, indem einfach ein beliebiges Byte in drei umgewandelt wird 7BIT Bytes. Ineffizient, aber es funktioniert (und beachte, dass der Kommentar, dass es nicht möglich ist, sowohl Dateinamen als auch binäre Daten zu senden, falsch ist; Sie senden es einfach als ein anderes Schlüssel / Wert-Paar).

Das Problem mit multipart/form-data ist, dass das Grenztrennzeichen in den Dateidaten nicht vorhanden sein darf (siehe RFC2388; Abschnitt 5.2 enthält auch eine ziemlich lahme Ausrede dafür, keinen richtigen Aggregat-MIME-Typ zu haben, der dieses Problem vermeidet).

Also, auf den ersten Blick, multipart/form-data ist überhaupt wertlos irgendein Datei-Upload, binär oder nicht Wenn Sie Ihre Grenze nicht richtig wählen, dann Sie werden eventuell ein Problem, egal ob Sie reinen Text oder eine rohe Binärdatei senden - der Server findet eine Grenze an der falschen Stelle, und Ihre Datei wird abgeschnitten oder der POST schlägt fehl.

Der Schlüssel besteht darin, eine Codierung und eine Begrenzung auszuwählen, sodass die ausgewählten Begrenzungszeichen nicht in der codierten Ausgabe angezeigt werden können. Eine einfache Lösung ist zu verwenden base64 (machen nicht verwende rohe Binärdatei). Im base64 3 willkürliche Bytes werden in vier 7-Bit-Zeichen codiert, wobei der Ausgangszeichensatz ist [A-Za-z0-9+/=] (dh alphanumerisch, oder '+', '/', '='). = ist ein Sonderfall und darf nur am Ende der codierten Ausgabe als Single erscheinen = oder ein Doppel ==. Wählen Sie nun Ihre Grenze als 7-Bit-ASCII-Zeichenfolge, die nicht angezeigt werden kann base64 Ausgabe. Viele Möglichkeiten, die Sie im Internet sehen, scheitern bei diesem Test - den MDN-Formularen DokumenteZum Beispiel, verwenden Sie "Blob" als Grenze beim Senden von Binärdaten - nicht gut. Etwas wie "! Blob!" wird nie in erscheinen base64 Ausgabe.


106
2018-04-18 11:08



Ich glaube nicht, dass HTTP in multipart oder x-www-form-urlencoded auf POST beschränkt ist. Das Inhaltstyp-Header ist orthogonal zur HTTP-POST-Methode (Sie können den MIME-Typ füllen, der zu Ihnen passt). Dies ist auch der Fall für typische auf HTML-Darstellungen basierende Webapps (z. B. wurden json-Nutzdaten zum Übertragen von Nutzdaten für ajax-Anforderungen sehr populär).

In Bezug auf Restful API über HTTP waren die am häufigsten verwendeten Inhaltstypen, mit denen ich in Kontakt gekommen bin, application / xml und application / json.

Anwendung / xml:

  • data-size: XML sehr ausführlich, aber normalerweise kein Problem bei der Verwendung von Komprimierung und der Annahme, dass der Schreibzugriffsfall (zB durch POST oder PUT) als Lesezugriff viel seltener ist (in vielen Fällen <3% des gesamten Datenverkehrs) ). Selten gab es Fälle, in denen ich die Schreibleistung optimieren musste
  • Existenz von Nicht-ASCII-Zeichen: Sie können UTF-8 als Codierung in XML verwenden
  • Existenz von Binärdaten: müsste Base64-Codierung verwenden
  • Dateiname-Daten: Sie können dieses Inside-Feld in XML kapseln

Anwendung / json

  • Datengröße: kompakter weniger als XML, noch Text, aber Sie können komprimieren
  • Nicht-ASCII-Zeichen: JSON ist UTF-8
  • Binärdaten: base64 (siehe auch JSON-Binär-Frage)
  • filename data: kapselt als eigenes Feld innerhalb von json ein

Binärdaten als eigene Ressource

Ich würde versuchen, Binärdaten als eigenes Asset / Ressource darzustellen. Es fügt einen weiteren Anruf hinzu, aber entkoppelt die Sachen besser. Beispielbilder:

POST /images
Content-type: multipart/mixed; boundary="xxxx" 
... multipart data

201 Created
Location: http://imageserver.org/../foo.jpg  

In späteren Ressourcen könnten Sie einfach die binäre Ressource als Link einbinden:

<main-resource>
 ...
 <link href="http://imageserver.org/../foo.jpg"/>
</main-resource>

82
2017-10-24 16:46



Ich stimme viel zu, was Manuel gesagt hat. In der Tat beziehen sich seine Kommentare auf diese URL ...

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

... welche Staaten:

Der Inhaltstyp   "application / x-www-form-urlencoded" ist   ineffizient für das Senden groß   Mengen von Binärdaten oder Text   enthält Nicht-ASCII-Zeichen. Das   Inhaltstyp "Multipart / Formulardaten"   sollte für die Einreichung von Formularen verwendet werden   die Dateien enthalten, Nicht-ASCII-Daten,   und binäre Daten.

Für mich würde es jedoch auf Tool- / Framework-Support hinauslaufen.

  • Welche Werkzeuge und Frameworks machen Sie? erwarte, dass deine API-Benutzer aufbauen ihre apps mit?
  • Haben sie Frameworks oder Komponenten, die sie verwenden können das bevorzugen eine Methode über die andere?

Wenn Sie eine klare Vorstellung von Ihren Nutzern erhalten und wissen, wie sie Ihre API nutzen, hilft Ihnen dies bei der Entscheidung. Wenn Sie das Hochladen von Dateien für Ihre API-Benutzer schwer machen, werden sie weggehen, und Sie werden viel Zeit darauf verwenden, sie zu unterstützen.

Nebenbei wäre die Tool-Unterstützung, die Sie haben, um Ihre API zu schreiben, und wie einfach es für Sie ist, einen Upload-Mechanismus gegenüber dem anderen unterzubringen.


26
2017-10-27 12:08



Nur ein kleiner Hinweis von meiner Seite zum Hochladen von HTML5-Canvas-Bilddaten:

Ich arbeite an einem Projekt für eine Druckerei und hatte Probleme, Bilder auf den Server hochzuladen, der von einem HTML5 kam canvas Element. Ich habe mindestens eine Stunde lang gekämpft und es ist mir nicht gelungen, das Bild korrekt auf meinem Server zu speichern.

Sobald ich das eingestellt habe contentType option von meinem jQuery ajax anzurufen application/x-www-form-urlencoded alles lief richtig und die base64-codierten Daten wurden korrekt interpretiert und erfolgreich als Bild gespeichert.


Vielleicht hilft das jemandem!


0
2017-12-10 15:07