Que signifie enctype='multipart/form-data'
dans un formulaire HTML et quand devrions-nous l’utiliser?
Lorsque vous effectuez une demande POST, vous devez encoder les données qui forment le corps de la demande d'une manière ou d'une autre.
Les formulaires HTML fournissent trois méthodes d’encodage.
application/x-www-form-urlencoded
_ (valeur par défaut)multipart/form-data
_text/plain
_Des travaux étaient en cours pour ajouter application/json
, mais cela a été abandonné.
(D'autres encodages sont possibles avec les requêtes HTTP générées par d'autres moyens qu'une soumission de formulaire HTML.)
Les spécificités des formats importent peu à la plupart des développeurs. Les points importants sont:
text/plain
_.Lorsque vous écrivez du code côté client:
multipart/form-data
_ lorsque votre formulaire comprend un élément _<input type="file">
_multipart/form-data
_ ou _application/x-www-form-urlencoded
_ mais _application/x-www-form-urlencoded
_ sera plus efficaceLorsque vous écrivez du code côté serveur:
La plupart (comme Perl _CGI->param
_ ou celle exposée par PHP _$_POST
_ superglobal) se chargeront des différences pour vous. Ne cherchez pas à analyser l’entrée brute reçue par le serveur.
Parfois, vous trouverez une bibliothèque qui ne peut pas gérer les deux formats. La bibliothèque la plus populaire de Node.js pour la gestion des données de formulaire est analyseur de corps qui ne peut pas gérer les demandes en plusieurs parties (mais dispose d'une documentation qui recommande certaines alternatives qui le peuvent).
Si vous écrivez (ou déboguez) une bibliothèque pour analyser ou générer les données brutes, vous devez commencer à vous soucier du format. Vous voudrez peut-être aussi le savoir par intérêt.
_application/x-www-form-urlencoded
_ est plus ou moins la même chose qu'une chaîne de requête à la fin de l'URL.
_multipart/form-data
_ est nettement plus compliqué, mais il permet d'inclure des fichiers entiers dans les données. Un exemple de résultat peut être trouvé dans le spécification HTML 4 .
_text/plain
_ est introduit par HTML 5 et est utile uniquement pour le débogage - de la spécification : Ils ne peuvent pas être interprétés de manière fiable par ordinateur - et je dirais que les autres combinés avec des outils (comme l'onglet Net dans les outils de développement de la plupart des navigateurs) sont meilleurs pour cela).
quand devrions-nous l'utiliser
La réponse de Quentin est correcte: utilisez _multipart/form-data
_ si le formulaire contient un fichier téléchargé et _application/x-www-form-urlencoded
_ sinon, qui est la valeur par défaut si vous omettez enctype
.
Je vais:
Il y a trois possibilités pour enctype
:
application/x-www-form-urlencoded
multipart/form-data
(la spécification pointe vers RFC7578 )text/plain
. Ceci n'est "pas interprétable de manière fiable par ordinateur", il ne devrait donc jamais être utilisé en production, et nous n'allons pas approfondir la question.Une fois que vous voyez un exemple de chaque méthode, son fonctionnement et le moment d'utilisation de chacune d'entre elles deviennent évidents.
Vous pouvez produire des exemples en utilisant:
nc -l
_ ou un serveur ECHO: serveur de test HTTP acceptant les demandes GET/POSTEnregistrez le formulaire dans un fichier minimal _.html
_:
_<!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 défini la valeur de texte par défaut sur _aωb
_, ce qui signifie _aωb
_ car _ω
_ est _U+03C9
_, qui sont les octets _61 CF 89 62
_ en UTF-8.
Créer 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
_
Lancer notre petit serveur echo:
_while true; do printf '' | nc -l 8000 localhost; done
_
Ouvrez le code HTML de votre navigateur, sélectionnez les fichiers, 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.
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 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').
Par conséquent, il est clair que:
_Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
_ définit le type de contenu sur _multipart/form-data
_ et indique que les champs sont séparés par la chaîne boundary
donnée.
chaque champ contient des 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 prochaine chaîne de limite. Le navigateur doit choisir une limite qui n'apparaîtra dans aucun des champs. C'est pourquoi la limite peut varier d'une requête à l'autre.
Parce que nous avons la limite unique, aucun codage des données n'est nécessaire: les données binaires sont envoyées telles quelles.
TODO: quelle est la taille de la frontière optimale (log(N)
je parie), et le nom/la durée d'exécution de l'algorithme qui le trouve? Demandé à: https://cs.stackexchange.com/questions/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 cela a-t-il été déterminé exactement à l'adresse suivante: Comment le type mime d'un fichier téléchargé est-il déterminé par le navigateur?
Modifiez maintenant la variable enctype
en _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
_
Clairement, les données du fichier n’ont pas été envoyées, mais 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 usuels tels que a
et b
ont été envoyés dans un octet, tandis que ceux non imprimables tels que _0xCF
_ et _0x89
_ ont été repris 3 octets chacun: _%CF%89
_!
Les téléchargements de fichiers contiennent souvent beaucoup de caractères non imprimables (par exemple, des images), alors que les formes de texte ne le font presque jamais.
D'après les exemples, nous avons vu que:
_multipart/form-data
_: ajoute quelques octets d'en-tête de limite au message et doit passer du temps à le calculer, mais envoie chaque octet sur 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 voudrions pas, car cela 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 temps système, donc nous l'utilisons simplement.
enctype='multipart/form-data
est un type de codage permettant d'envoyer des fichiers via POST. Tout simplement, sans ce codage, les fichiers ne peuvent pas être envoyés via POST.
Si vous souhaitez autoriser un utilisateur à télécharger un fichier via un formulaire, vous devez utiliser ceci enctype.
Lors de la soumission d'un formulaire, vous indiquez à votre navigateur d'envoyer, via le protocole HTTP, un message sur le réseau, correctement enveloppé dans une structure de message du protocole TCP/IP. Une page HTML permet d'envoyer des données au serveur: en utilisant <form>
s.
Lorsqu'un formulaire est soumis, si une demande HTTP est créée et envoyée au serveur, le message contient les noms de champs du formulaire et les valeurs renseignées par l'utilisateur. Cette transmission peut se produire avec les méthodes HTTP POST
ou GET
.
POST
indique à votre navigateur de créer un message HTTP et de placer tout son contenu dans le corps du message (moyen très utile de procéder, plus sûr et plus flexible).GET
soumettra les données du formulaire dans la chaîne de requête . Il y a des contraintes sur la représentation et la longueur des données.L'attribut enctype
n'a de sens que lorsque vous utilisez la méthode POST
. Lorsque spécifié, il demande au navigateur d'envoyer le formulaire en codant son contenu d'une manière spécifique. De MDN - Form enctype :
Lorsque la valeur de l'attribut de méthode est post, enctype est le type de contenu MIME utilisé pour soumettre le formulaire au serveur.
application/x-www-form-urlencoded
: C'est la valeur par défaut. Lorsque le formulaire est envoyé, tous les noms et toutes les valeurs sont collectés et codage d'URL est effectué sur la chaîne finale.multipart/form-data
: Les caractères ne sont PAS encodés. Ceci est important lorsque le formulaire dispose d'un contrôle de téléchargement de fichier. Vous souhaitez envoyer le fichier binaire, ce qui garantit que le flux binaire n'est pas modifié.text/plain
: Les espaces sont convertis, mais aucun autre encodage n'est effectué.Lors de la soumission de formulaires, des problèmes de sécurité peuvent survenir, comme indiqué dans la section RFC 7578 section 7: données de formulaire multipart - Considérations de sécurité :
Tous les logiciels de traitement de formulaires doivent traiter les données de formulaire fournies par l'utilisateur.
avec tact, car il contient souvent des informations confidentielles ou personnelles.
données d'identification. Les fonctionnalités de "remplissage automatique" des formulaires sont largement utilisées dans les navigateurs Web; ceux-ci pourraient être utilisés pour tromper les utilisateurs à
envoyer sans le savoir des informations confidentielles en complétant autrement
tâches inoffensives. multipart/form-data ne fournit aucune fonctionnalité
pour vérifier l'intégrité, assurer la confidentialité, éviter l'utilisateur
confusion ou d’autres caractéristiques de sécurité; ces préoccupations doivent être
traitées par les applications de remplissage et d’interprétation de données.Les applications qui reçoivent des formulaires et les traitent doivent veiller à ne pas renvoyer de données au site de traitement de formulaire demandeur qui n'était pas destiné à être envoyé.
Il est important d’interpréter le nom de fichier du contenu.
Champ d'en-tête d'élimination pour ne pas écraser par inadvertance les fichiers du
Espace fichier du destinataire.
Cela vous concerne si vous êtes un développeur et que votre serveur traitera les formulaires soumis par les utilisateurs, susceptibles de contenir des informations sensibles.
enctype='multipart/form-data'
signifie qu'aucun caractère ne sera codé. c'est pourquoi ce type est utilisé lors du téléchargement de fichiers sur le serveur.
Donc, multipart/form-data
est utilisé lorsqu'un formulaire nécessite le téléchargement de données binaires, telles que le contenu d'un fichier.
Définissez l'attribut de méthode sur POST car le contenu du fichier ne peut pas être placé dans un paramètre d'URL à l'aide d'un formulaire.
Définissez la valeur de enctype sur multipart/form-data car les données seront divisées en plusieurs parties, une pour chaque fichier et une pour le texte du corps du formulaire pouvant être envoyé avec elles.
Habituellement, c’est lorsque vous avez un formulaire POST qui nécessite de transférer un fichier sous forme de données ... Cela indiquera au serveur comment il va coder les données transférées. Dans ce cas, elles ne seront pas codées car il ne fera que transférer et télécharger les fichiers sur le serveur, comme par exemple lors du téléchargement d'une image ou d'un fichier PDF