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 le faire :
- ajouter quelques références HTML5 supplémentaires
- expliquer por qué il a raison avec un exemple de soumission de formulaire
Références HTML5
Hay trois possibilités para enctype
:
Comment générer les exemples
Une fois que vous avez vu 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 :
Sauvegarder le formulaire dans un minimum .html
fichier :
<!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 définissons la valeur du texte par défaut comme suit aωb
ce qui signifie aωb
parce 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
Lancez notre petit serveur d'écho :
while true; do printf '' | nc -l 8000 localhost; done
Ouvrez le 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 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 le vérifier 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 comme multipart/form-data
et indique que les champs sont séparés par les caractères suivants boundary
chaîne.
Mais notez que le :
boundary=---------------------------735323031399963166993862150
a deux dadhes de moins --
que la barrière réelle
-----------------------------735323031399963166993862150
En effet, la norme exige que la frontière commence par deux tirets. --
. Les autres tirets semblent être simplement la façon dont Firefox a choisi d'implémenter la limite arbitraire. La RFC 7578 mentionne clairement que ces deux tirets de tête --
sont nécessaires :
4.1. Paramètre "Boundary" de multipart/form-data
Comme pour les autres types multipartites, les parties sont délimitées par un signe délimiteur de frontière, construit à l'aide de CRLF, de "--" et de la valeur du paramètre du paramètre "boundary".
application/x-www-form-urlencoded
Maintenant, changez le enctype
a application/x-www-form-urlencoded
rechargez le navigateur, et soumettez à nouveau.
Firefox 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
Il est clair que les données du fichier n'ont pas été envoyées, seulement les noms de base. Cela ne peut donc pas être utilisé pour les fichiers.
En ce qui concerne le champ de texte, nous voyons que les caractères imprimables habituels comme a
y b
ont été envoyés dans un octet, tandis que les caractères non imprimables comme 0xCF
y 0x89
a 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 de texte ne le font presque jamais.
D'après les exemples, nous avons vu que :
-
multipart/form-data
: ajoute quelques octets d'overhead de frontière au message, et doit passer un certain temps à le calculer, mais envoie chaque octet dans un seul octet.
-
application/x-www-form-urlencoded
: a une limite d'un seul octet par champ ( &
), mais ajoute un linéaire facteur de surcharge 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, parce que 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 frais généraux, donc nous l'utilisons simplement.
0 votes
Je n'ai pas utilisé de renifleur depuis un certain temps mais si vous voulez voir ce qui est envoyé dans votre requête (puisqu'elle est adressée au serveur, c'est une requête), reniflez-la. Cette question est trop large. SO est plus pour des questions de programmation spécifiques.
0 votes
...en tant que renifleur, violoniste est mon arme de prédilection. Vous pouvez même créer vos propres demandes de test pour voir comment elles s'affichent.
0 votes
Pour les personnes intéressées, voir également "
MAX_FILE_SIZE
en PHP - quel intérêt ?" sur stackoverflow.com/q/1381364/6329510 votes
Je trouve que MAX_FILE_SIZE est bizarre, car je peux modifier mon html dans chrome à 100000000 avant de le poster pour qu'il affiche une meilleure valeur. Soit 1. l'avoir dans un cookie avec un hachage sécurisé via un sel, de sorte que le cookie, s'il est modifié, le serveur peut valider et lancer une exception (comme le font webpieces ou playframework) ou une sorte de validation de formulaire pour vérifier que les choses n'ont pas changé. @0xSina