Wenn ich ein einfaches Formular wie dieses mit einer angehängten Datei abschicke:
<form enctype="multipart/form-data" action="http://localhost:3000/upload?upload_progress_id=12344" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
Wie wird die Datei intern gesendet? Wird die Datei als Teil des HTTP-Körpers als Daten gesendet? In den Kopfzeilen dieser Anfrage wird nichts im Zusammenhang mit dem Namen der Datei angezeigt.
Ich möchte nur die internen Funktionen des HTTP beim Senden einer Datei kennen.
http
file-upload
0xSina
quelle
quelle
MAX_FILE_SIZE
in PHP - was ist der Sinn" auf stackoverflow.com/q/1381364/632951Antworten:
Lassen Sie uns einen Blick darauf werfen, was passiert, wenn Sie eine Datei auswählen und Ihr Formular senden (der Kürze halber habe ich die Überschriften abgeschnitten):
HINWEIS: Jeder Begrenzungszeichenfolge muss ein zusätzliches Präfix vorangestellt werden
--
, genau wie am Ende der letzten Begrenzungszeichenfolge. Das obige Beispiel enthält dies bereits, kann jedoch leicht übersehen werden. Siehe Kommentar von @Andreas unten.Anstelle einer URL, die die Formularparameter codiert, werden die Formularparameter (einschließlich der Dateidaten) als Abschnitte in einem mehrteiligen Dokument im Hauptteil der Anforderung gesendet.
Im obigen Beispiel sehen Sie die Eingabe
MAX_FILE_SIZE
mit dem im Formular festgelegten Wert sowie einen Abschnitt mit den Dateidaten. Der Dateiname ist Teil desContent-Disposition
Headers.Die vollständigen Details finden Sie hier .
quelle
Das Format wird
multipart/form-data
wie folgt aufgerufen : Was bedeutet enctype = 'multipart / form-data'?Ich werde:
HTML5-Referenzen
Es gibt drei Möglichkeiten für
enctype
:x-www-urlencoded
multipart/form-data
(Spezifikation zeigt auf RFC2388 )text-plain
. Dies ist "vom Computer nicht zuverlässig interpretierbar", daher sollte es niemals in der Produktion verwendet werden, und wir werden nicht weiter darauf eingehen.So generieren Sie die Beispiele
Sobald Sie ein Beispiel für jede Methode sehen, wird klar, wie sie funktionieren und wann Sie jede verwenden sollten.
Sie können Beispiele erstellen mit:
nc -l
oder ein ECHO-Server: HTTP-Testserver, der GET / POST-Anforderungen akzeptiertSpeichern Sie das Formular in einer minimalen
.html
Datei:Wir setzen den Standardtextwert auf
aωb
, was bedeutet ,aωb
daω
istU+03C9
, der die Bytes61 CF 89 62
in UTF-8.Erstellen Sie Dateien zum Hochladen:
Führen Sie unseren kleinen Echoserver aus:
Öffnen Sie den HTML-Code in Ihrem Browser, wählen Sie die Dateien aus, klicken Sie auf Senden und überprüfen Sie das Terminal.
nc
druckt die empfangene Anfrage.Getestet am: Ubuntu 14.04.3,
nc
BSD 1.105, Firefox 40.mehrteilige / Formulardaten
Firefox gesendet:
Für die Binärdatei und das Textfeld werden die Bytes
61 CF 89 62
(aωb
in UTF-8) buchstäblich gesendet. Sie könnten das mit überprüfennc -l localhost 8000 | hd
, was besagt, dass die Bytes:wurden gesendet (
61
== 'a' und62
== 'b').Daher ist es klar, dass:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Setzt den Inhaltstyp aufmultipart/form-data
und gibt an, dass die Felder durch die angegebeneboundary
Zeichenfolge getrennt sind.Beachten Sie jedoch, dass die:
hat zwei weniger Dadhes
--
als die eigentliche BarriereDies liegt daran, dass der Standard erfordert, dass die Grenze mit zwei Strichen beginnt
--
. Die anderen Striche scheinen genau so zu sein, wie Firefox die willkürliche Grenze implementiert hat. In RFC 7578 wird klar erwähnt, dass diese beiden führenden Striche--
erforderlich sind:Jedes Feld erhält einige Unterüberschriften vor seinen Daten :
Content-Disposition: form-data;
, das Feldname
, dasfilename
, gefolgt von den Daten.Der Server liest die Daten bis zur nächsten Grenzzeichenfolge. Der Browser muss eine Grenze auswählen, die in keinem der Felder angezeigt wird. Aus diesem Grund kann die Grenze zwischen den Anforderungen variieren.
Da wir die eindeutige Grenze haben, ist keine Codierung der Daten erforderlich: Binärdaten werden unverändert gesendet.
TODO: Was ist die optimale Grenzgröße (
log(N)
ich wette) und Name / Laufzeit des Algorithmus, der sie findet? Gefragt unter: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequencesContent-Type
wird automatisch vom Browser ermittelt.Wie es genau bestimmt wird, wurde gefragt unter: Wie wird der MIME-Typ einer hochgeladenen Datei vom Browser bestimmt?
application / x-www-form-urlencoded
Ändern Sie nun das
enctype
inapplication/x-www-form-urlencoded
, laden Sie den Browser neu und senden Sie es erneut.Firefox gesendet:
Offensichtlich wurden nicht die Dateidaten gesendet, sondern nur die Basisnamen. Dies kann also nicht für Dateien verwendet werden.
Wie für das Textfeld ein , so sehen wir , dass die üblichen druckbare Zeichen wie
a
undb
wurden in einem Byte, während nicht-druckbaren wie geschickt0xCF
und0x89
nahmen 3 Bytes je:%CF%89
!Vergleich
Das Hochladen von Dateien enthält häufig viele nicht druckbare Zeichen (z. B. Bilder), während Textformulare dies fast nie tun.
Aus den Beispielen haben wir gesehen, dass:
multipart/form-data
: Fügt der Nachricht ein paar Bytes Boundary Overhead hinzu und muss einige Zeit mit der Berechnung verbringen, sendet jedoch jedes Byte in einem Byte.application/x-www-form-urlencoded
: hat eine einzelne Bytegrenze pro Feld (&
), fügt jedoch für jedes nicht druckbare Zeichen einen linearen Overhead-Faktor von 3x hinzu .Selbst wenn wir Dateien mit senden könnten,
application/x-www-form-urlencoded
würden wir dies nicht wollen, weil es so ineffizient ist.Für druckbare Zeichen in Textfeldern spielt dies jedoch keine Rolle und erzeugt weniger Overhead. Daher verwenden wir es einfach.
quelle
Content-Disposition
undContent-Type
Attribute ändern , aber wie gehe ich mit dem 'Inhalt' um?Datei als binären Inhalt senden (ohne Formular oder FormData hochladen)
In den angegebenen Antworten / Beispielen wird die Datei (höchstwahrscheinlich) mit einem HTML-Formular oder mithilfe der FormData-API hochgeladen . Die Datei ist nur ein Teil der in der Anfrage gesendeten Daten, daher der
multipart/form-data
Content-Type
Header.Wenn Sie die Datei als einzigen Inhalt senden möchten, können Sie sie direkt als Anforderungshauptteil hinzufügen und den
Content-Type
Header auf den MIME-Typ der Datei setzen, die Sie senden. Der Dateiname kann imContent-Disposition
Header hinzugefügt werden . Sie können wie folgt hochladen:Wenn Sie keine Formulare verwenden (möchten) und nur eine einzige Datei hochladen möchten, ist dies der einfachste Weg, Ihre Datei in die Anfrage aufzunehmen.
quelle
Content-Type
aus dem Header in einer Datei speichern .Ich habe dieses Beispiel Java-Code:
und ich habe diese test.html Datei:
und schließlich hat die Datei, die ich zu Testzwecken verwenden werde, mit dem Namen a.dat den folgenden Inhalt:
Wenn Sie die obigen Bytes als ASCII- oder UTF-8-Zeichen interpretieren, stellen sie tatsächlich Folgendes dar:
Lassen Sie uns also unseren Java-Code ausführen , test.html in unserem bevorzugten Browser öffnen
a.dat
, das Formular hochladen und senden und sehen, was unser Server empfängt:Nun, ich bin nicht überrascht, die Zeichen 9ie zu sehen, weil wir Java angewiesen haben, sie zu drucken und sie als UTF-8-Zeichen zu behandeln. Sie können sie auch als Rohbytes lesen.
ist eigentlich der letzte HTTP-Header hier. Danach folgt der HTTP-Body, in dem Meta und Inhalt der von uns hochgeladenen Datei tatsächlich angezeigt werden.
quelle
http://www.tutorialspoint.com/http/http_messages.htm
quelle