In HTTP gibt es zwei Möglichkeiten, Daten zu POSTEN: application/x-www-form-urlencoded
und multipart/form-data
. Ich verstehe, dass die meisten Browser nur dann Dateien hochladen können, wenn sie multipart/form-data
verwendet werden. Gibt es zusätzliche Anleitungen, wann einer der Codierungstypen in einem API-Kontext verwendet werden soll (kein Browser beteiligt)? Dies könnte zB basieren auf:
- Datengröße
- Existenz von Nicht-ASCII-Zeichen
- Existenz auf (nicht codierten) Binärdaten
- die Notwendigkeit, zusätzliche Daten zu übertragen (wie Dateiname)
Grundsätzlich habe ich im Web bisher keine formelle Anleitung zur Verwendung der verschiedenen Inhaltstypen gefunden.
http
post
http-headers
max
quelle
quelle
Antworten:
TL; DR
Zusammenfassung; Wenn Sie binäre (nicht alphanumerische) Daten (oder eine Nutzlast mit beträchtlicher Größe) übertragen möchten, verwenden Sie
multipart/form-data
. Andernfalls verwenden Sieapplication/x-www-form-urlencoded
.Die von Ihnen erwähnten MIME-Typen sind die beiden
Content-Type
Header für HTTP-POST-Anforderungen, 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 sich ansehen, was jeder unter der Decke tut.Für
application/x-www-form-urlencoded
, aber eine große Abfragezeichenfolge des Körper der HTTP - Nachricht an den Server gesendet wird , im wesentlichen - Namen / Wert - Paare werden voneinander getrennt durch das Zeichen (&
) und Namen von Werten , getrennt durch die gleich sind Symbol (=
). Ein Beispiel hierfür wäre:MyVariableOne=ValueOne&MyVariableTwo=ValueTwo
Gemäß der Spezifikation :
Das bedeutet, dass für jedes nicht alphanumerische Byte, das in einem unserer Werte vorhanden ist, drei Bytes erforderlich sind, um es darzustellen. Bei großen Binärdateien ist die Verdreifachung der Nutzlast äußerst ineffizient.
Hier
multipart/form-data
kommt es ins Spiel. Bei dieser Methode zum Übertragen von Name / Wert-Paaren wird jedes Paar als "Teil" in einer MIME-Nachricht dargestellt (wie in anderen Antworten beschrieben). Teile werden durch eine bestimmte Zeichenfolgengrenze getrennt (speziell ausgewählt, damit diese Grenzzeichenfolge in keiner der Nutzdaten mit "Wert" vorkommt). Jeder Teil hat seine eigenen MIME-Header wieContent-Type
und insbesondereContent-Disposition
, die jedem Teil seinen "Namen" geben können. Das Wertstück jedes Namens / Wert-Paares ist die Nutzlast jedes Teils der MIME-Nachricht. Die MIME-Spezifikation bietet uns mehr Optionen bei der Darstellung des Nutzwerts - wir können eine effizientere Codierung von Binärdaten wählen, um Bandbreite zu sparen (z. B. Basis 64 oder sogar Roh-Binärdaten).Warum nicht die
multipart/form-data
ganze Zeit nutzen? Bei kurzen alphanumerischen Werten (wie bei den meisten Webformularen) überwiegt der Aufwand für das Hinzufügen aller MIME-Header die Einsparungen durch eine effizientere Binärcodierung erheblich.quelle
LESEN SIE MINDESTENS DEN ERSTEN PARA HIER!
Ich weiß, dass dies 3 Jahre zu spät ist, aber Matts (akzeptierte) Antwort ist unvollständig und wird Sie schließlich in Schwierigkeiten bringen. Der Schlüssel hier ist, dass, wenn Sie sich für die Verwendung entscheiden
multipart/form-data
, die Grenze nicht in den Dateidaten erscheinen darf , die der Server schließlich empfängt.Dies ist kein Problem
application/x-www-form-urlencoded
, da es keine Grenze gibt.x-www-form-urlencoded
kann auch immer mit Binärdaten umgehen, indem einfach ein beliebiges Byte in drei7BIT
Bytes umgewandelt wird. Ineffizient, aber es funktioniert (und beachten Sie, dass der Kommentar, dass Dateinamen und Binärdaten nicht gesendet werden können, falsch ist; Sie senden ihn einfach als ein weiteres Schlüssel / Wert-Paar).Das Problem dabei
multipart/form-data
ist, dass das Grenztrennzeichen nicht in den Dateidaten vorhanden sein darf (siehe RFC 2388 ; Abschnitt 5.2 enthält auch eine ziemlich lahme Entschuldigung dafür, dass kein geeigneter aggregierter MIME-Typ vorhanden ist, der dieses Problem vermeidet).Also, auf den ersten Blick,
multipart/form-data
ist von keinem Wert in haupt jede Datei - Upload, binär oder auf andere Weise. Wenn Sie Ihre Grenze nicht korrekt wählen, dann Sie wird schließlich ein Problem haben, ob Sie Text oder Raw - Binary sind zu senden - der Server eine Grenze an der falschen Stelle finden, und die Dateien werden abgeschnitten oder POST wird versagen.Der Schlüssel besteht darin, eine Codierung und eine Grenze so zu wählen, dass Ihre ausgewählten Grenzzeichen nicht in der codierten Ausgabe erscheinen können. Eine einfache Lösung ist die Verwendung
base64
(nicht nicht Raw - Binary verwenden). In base64 werden 3 beliebige Bytes in vier 7-Bit-Zeichen codiert, wobei der Ausgabezeichensatz[A-Za-z0-9+/=]
(dh alphanumerisch, '+', '/' oder '=') ist.=
ist ein Sonderfall und wird möglicherweise nur am Ende der codierten Ausgabe als Einzel-=
oder Doppelausgabe angezeigt==
. Wählen Sie nun Ihre Grenze als 7-Bit-ASCII-Zeichenfolge, die in derbase64
Ausgabe nicht angezeigt werden kann. Viele Auswahlmöglichkeiten, die Sie im Internet sehen, schlagen diesen Test fehl - das MDN bildet DokumenteVerwenden Sie beispielsweise "blob" als Grenze beim Senden von Binärdaten - nicht gut. Allerdings so etwas wie "! Blob!" wird niemals in derbase64
Ausgabe erscheinen .quelle
index === -1
.'()+-./:=
dann zu verwenden . Die zufällige Generierung mit Teilstring-Prüfung ist jedoch noch nicht abgeschlossen und kann mit einer Zeile erfolgen :while(true){r = rand(); if(data.indexOf(r) === -1){doStuff();break;}}
. Der Vorschlag von EML (Konvertierung in base64, nur um übereinstimmende Teilzeichenfolgen zu vermeiden) ist einfach seltsam, ganz zu schweigen von unnötigen Leistungseinbußen. Und all die Probleme umsonst, da der Einzeilenalgorithmus ebenso einfach und unkompliziert ist. Base64 soll nicht (ab) auf diese Weise verwendet werden, da der HTTP-Body alle 8-Bit- Oktette akzeptiert .Ich glaube nicht, dass HTTP auf POST in mehrteiligen oder x-www-form-urlencoded beschränkt ist. Der Content-Type-Header ist orthogonal zur HTTP-POST-Methode (Sie können den für Sie geeigneten MIME-Typ eingeben). Dies ist auch bei typischen Webapps auf der Basis von HTML-Darstellungen der Fall (z. B. wurde die json-Nutzlast für die Übertragung von Nutzdaten für Ajax-Anforderungen sehr beliebt).
In Bezug auf Restful API over HTTP sind application / xml und application / json die beliebtesten Inhaltstypen, mit denen ich in Kontakt gekommen bin.
application / xml:
Anwendung / json
Binärdaten als eigene Ressource
Ich würde versuchen, Binärdaten als eigenes Asset / Ressource darzustellen. Es fügt einen weiteren Anruf hinzu, entkoppelt aber das Zeug besser. Beispielbilder:
In späteren Ressourcen können Sie die binäre Ressource einfach als Link einbinden:
quelle
Ich stimme vielem 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:
Für mich würde es jedoch auf die Unterstützung von Tools / Frameworks ankommen.
Wenn Sie eine klare Vorstellung von Ihren Benutzern haben und wissen, wie sie Ihre API verwenden, hilft Ihnen dies bei der Entscheidung. Wenn Sie Ihren API-Benutzern das Hochladen von Dateien erschweren, werden sie entfernt, und Sie werden viel Zeit damit verbringen, sie zu unterstützen.
Zweitens wäre die Toolunterstützung, die SIE zum Schreiben Ihrer API haben, und wie einfach es für Sie ist, einen Upload-Mechanismus über den anderen zu setzen.
quelle
Nur ein kleiner Hinweis von meiner Seite zum Hochladen von HTML5-Canvas-Bilddaten:
Ich arbeite an einem Projekt für eine Druckerei und hatte einige Probleme beim Hochladen von Bildern auf den Server, die von einem HTML5-
canvas
Element stammen. Ich hatte mindestens eine Stunde lang Probleme und konnte das Bild nicht richtig auf meinem Server speichern.Nachdem ich die
contentType
Option meines jQuery-Ajax-Aufrufs aufapplication/x-www-form-urlencoded
alles gesetzt hatte, lief alles richtig und die base64-codierten Daten wurden korrekt interpretiert und erfolgreich als Bild gespeichert.Vielleicht hilft das jemandem!
quelle
Wenn Sie Content-Type = x-www-urlencoded-form verwenden müssen, verwenden Sie NICHT FormDataCollection als Parameter: In asp.net Core 2+ hat FormDataCollection keine Standardkonstruktoren, die von Formatierern benötigt werden. Verwenden Sie stattdessen IFormCollection:
quelle