Wie wird die Datei intern gesendet?
Das Format wird multipart/form-data
wie folgt aufgerufen : Was bedeutet enctype = 'multipart / form-data'?
Ich werde:
- Fügen Sie weitere HTML5-Referenzen hinzu
- Erklären Sie, warum er Recht hat, mit einem Beispiel zum Senden eines Formulars
HTML5-Referenzen
Es gibt drei Möglichkeiten für enctype
:
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:
Speichern Sie das Formular in einer minimalen .html
Datei:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
Wir setzen den Standardtextwert auf aωb
, was bedeutet , aωb
da ω
ist U+03C9
, der die Bytes 61 CF 89 62
in UTF-8.
Erstellen Sie Dateien zum Hochladen:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
Führen Sie unseren kleinen Echoserver aus:
while true; do printf '' | nc -l 8000 localhost; done
Ö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:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
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üfen nc -l localhost 8000 | hd
, was besagt, dass die Bytes:
61 CF 89 62
wurden gesendet ( 61
== 'a' und 62
== 'b').
Daher ist es klar, dass:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Setzt den Inhaltstyp auf multipart/form-data
und gibt an, dass die Felder durch die angegebene boundary
Zeichenfolge getrennt sind.
Beachten Sie jedoch, dass die:
boundary=---------------------------735323031399963166993862150
hat zwei weniger Dadhes --
als die eigentliche Barriere
-----------------------------735323031399963166993862150
Dies 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:
4.1. "Grenze" Parameter von mehrteiligen / Formulardaten
Wie bei anderen mehrteiligen Typen werden die Teile durch einen Begrenzungsbegrenzer begrenzt, der unter Verwendung von CRLF, "-" und dem Wert des Parameters "Grenze" erstellt wird.
Jedes Feld erhält einige Unterüberschriften vor seinen Daten : Content-Disposition: form-data;
, das Feld name
, das filename
, 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-sequences
Content-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
in application/x-www-form-urlencoded
, laden Sie den Browser neu und senden Sie es erneut.
Firefox gesendet:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
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
und b
wurden in einem Byte, während nicht-druckbaren wie geschickt 0xCF
und 0x89
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.