Comment envoie-t-il le fichier en interne?
Le format est appelé multipart/form-data
, comme demandé à: Que signifie enctype = 'multipart / form-data'?
Je vais:
- ajouter des références HTML5 supplémentaires
- expliquer pourquoi il a raison avec un formulaire soumettre un exemple
Références HTML5
Il existe trois possibilités pour enctype
:
Comment générer les exemples
Une fois que vous voyez un exemple de chaque méthode, il devient évident comment elles fonctionnent et quand vous devez les utiliser.
Vous pouvez produire des exemples en utilisant:
Enregistrez le formulaire dans un .html
fichier minimal :
<!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>
Nous avons mis la valeur de texte par défaut aωb
, ce qui signifie aωb
que ω
est U+03C9
, qui sont les octets 61 CF 89 62
en UTF-8.
Créez des fichiers à télécharger:
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
Exécutez notre petit serveur d'écho:
while true; do printf '' | nc -l 8000 localhost; done
Ouvrez le code HTML sur votre navigateur, sélectionnez les fichiers et cliquez sur soumettre et vérifiez le terminal.
nc
imprime la demande reçue.
Testé sur: Ubuntu 14.04.3, nc
BSD 1.105, Firefox 40.
multipart / form-data
Firefox a envoyé:
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--
Pour le fichier binaire et le champ de texte, les octets 61 CF 89 62
( aωb
en UTF-8) sont envoyés littéralement. Vous pouvez vérifier cela avec nc -l localhost 8000 | hd
, qui dit que les octets:
61 CF 89 62
ont été envoyés ( 61
== 'a' et 62
== 'b').
Il est donc clair que:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
définit le type de contenu sur multipart/form-data
et indique que les champs sont séparés par la boundary
chaîne donnée .
Mais notez que:
boundary=---------------------------735323031399963166993862150
a deux papas de moins --
que la barrière réelle
-----------------------------735323031399963166993862150
En effet, la norme requiert que la limite commence par deux tirets --
. Les autres tirets semblent être juste la façon dont Firefox a choisi d'implémenter la frontière arbitraire. La RFC 7578 mentionne clairement que ces deux tirets principaux --
sont requis:
4.1. "Boundary" Parameter of multipart / form-data
Comme pour les autres types de parties multiples, les pièces sont délimitées par un délimiteur de limite, construit à l'aide de CRLF, "-" et de la valeur du paramètre "limite".
chaque champ obtient des sous-en-têtes avant ses données:, Content-Disposition: form-data;
le champ name
, le filename
, suivi des données.
Le serveur lit les données jusqu'à la chaîne de limite suivante. Le navigateur doit choisir une limite qui n'apparaîtra dans aucun des champs, c'est pourquoi la limite peut varier entre les demandes.
Parce que nous avons la frontière unique, aucun encodage des données n'est nécessaire: les données binaires sont envoyées telles quelles.
TODO: quelle est la taille optimale de la limite ( log(N)
je parie) et le nom / le temps d'exécution de l'algorithme qui la trouve? Demandé à: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
Content-Type
est automatiquement déterminé par le navigateur.
Comment il est déterminé exactement a été demandé à: Comment le type MIME d'un fichier téléchargé est-il déterminé par le navigateur?
application / x-www-form-urlencoded
Maintenant, changez le enctype
en application/x-www-form-urlencoded
, rechargez le navigateur et soumettez à nouveau.
Firefox a envoyé:
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
De toute évidence, les données du fichier n'ont pas été envoyées, uniquement les noms de base. Donc, cela ne peut pas être utilisé pour les fichiers.
En ce qui concerne le champ de texte, nous voyons que les caractères imprimables habituels aiment a
et b
ont été envoyés dans un octet, tandis que ceux non imprimables aiment 0xCF
et 0x89
ont pris 3 octets chacun %CF%89
:!
Comparaison
Les téléchargements de fichiers contiennent souvent de nombreux caractères non imprimables (par exemple des images), alors que les formulaires texte ne le font presque jamais.
D'après les exemples, nous avons vu que:
multipart/form-data
: ajoute quelques octets de surcharge de limite au message, et doit passer un certain temps à le calculer, mais envoie chaque octet dans un octet.
application/x-www-form-urlencoded
: a une limite d'un octet par champ ( &
), mais ajoute un facteur de surcharge linéaire de 3x pour chaque caractère non imprimable.
Par conséquent, même si nous pouvions envoyer des fichiers avec application/x-www-form-urlencoded
, nous ne le voudrions pas, car c'est tellement inefficace.
Mais pour les caractères imprimables trouvés dans les champs de texte, cela n'a pas d'importance et génère moins de surcharge, nous ne l'utilisons donc que.