web-dev-qa-db-fra.com

Que signifie enctype = 'multipart / form-data'?

Que signifie enctype='multipart/form-data' dans un formulaire HTML et quand devrions-nous l’utiliser?

1251
EBAG

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:

  • Ne jamais utiliser _text/plain_.

Lorsque vous écrivez du code côté client:

  • utilisez _multipart/form-data_ lorsque votre formulaire comprend un élément _<input type="file">_
  • sinon vous pouvez utiliser _multipart/form-data_ ou _application/x-www-form-urlencoded_ mais _application/x-www-form-urlencoded_ sera plus efficace

Lorsque vous écrivez du code côté serveur:

  • Utiliser une bibliothèque de traitement de formulaire pré-écrite

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).

1409
Quentin

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:

  • ajouter quelques références HTML5 supplémentaires
  • expliquer pourquoi il a raison avec un exemple d'envoi de formulaire

Références HTML5

Il y a trois possibilités pour enctype:

Comment générer les exemples

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:

Enregistrez 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&#x03C9;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&#x03C9;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.

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 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?

application/x-www-form-urlencoded

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_!

Comparaison

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.

85
Matt Asbury

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.

Comment envoyer votre formulaire au serveur

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é.

Sécurité

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.

73
Andry

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.

32
GP Singh

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.

8
sandy
  • enctype (ENC ode TYPE) spécifie comment les données de formulaire doivent être codées lors de leur envoi au serveur.
  • multipart/form-data est l'une des valeurs de l'attribut enctype, utilisé dans les éléments de formulaire comportant un téléchargement de fichier. multi-part signifie que les données de formulaire se divisent en plusieurs parties et sont envoyées au serveur.
0
Premraj

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

0
Eric