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


Réponses:


1570

Lorsque vous effectuez une demande POST, vous devez coder les données qui forment le corps de la demande d'une manière ou d'une autre.

Les formulaires HTML proposent trois méthodes de codage.

  • application/x-www-form-urlencoded (le défaut)
  • multipart/form-data
  • text/plain

Des travaux étaient en cours pour l'ajout application/json, mais cela a été abandonné.

(D'autres encodages sont possibles avec des requêtes HTTP générées en utilisant d'autres moyens qu'une soumission de formulaire HTML. JSON est un format courant à utiliser avec les services Web et certains utilisent toujours SOAP.)

Les détails des formats n'ont pas d'importance pour la plupart des développeurs. Les points importants sont:

  • Ne jamais utiliser text/plain.

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

  • utiliser multipart/form-datalorsque votre formulaire contient des <input type="file">éléments
  • sinon vous pouvez utiliser multipart/form-dataou application/x-www-form-urlencodedmais application/x-www-form-urlencodedsera plus efficace

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

  • Utiliser une bibliothèque de gestion de formulaires pré-écrite

La plupart (comme Perl CGI->paramou celui exposé par le $_POSTsuperglobal de PHP ) s'occuperont des différences pour vous. Ne vous embêtez pas à essayer d'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 gérer les données de formulaire est l' analyseur de corps qui ne peut pas gérer les demandes en plusieurs parties (mais possède une documentation qui recommande des alternatives qui le peuvent).


Si vous écrivez (ou déboguez) une bibliothèque pour analyser ou générer les données brutes, alors 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 identique à une chaîne de requête à la fin de l'URL.

multipart/form-dataest beaucoup plus compliqué, mais il permet d'inclure des fichiers entiers dans les données. Un exemple du résultat peut être trouvé dans la spécification HTML 4 .

text/plainest introduit par HTML 5 et n'est utile que pour le débogage - à partir de la spécification : ils ne sont pas interprétables de manière fiable par ordinateur - et je dirais que les autres combinés avec des outils (comme le panneau réseau dans les outils de développement de la plupart des navigateurs) sont meilleurs pour ça).


5
@Quentin Excusez-moi, quel sera le problème probable si nous utilisons plusieurs parties pour toutes les formes? avec et sans fichiers.
Webinan

12
Cela n'a pas de sens pour les formulaires GET et augmente la taille du fichier des demandes.
Quentin

@Quentin les données de formulaire en plusieurs parties sont-elles envoyées en tant que flux par défaut?
Growler

L'enc dans enctype représente-t-il quelque chose?
Philip Rego

1
"Les formulaires HTML offrent trois méthodes de codage ENC "
Quentin

449

quand devrions-nous l'utiliser

La réponse de Quentin est juste: utilisez multipart/form-datasi le formulaire contient un téléchargement de fichier, et application/x-www-form-urlencodedsinon, c'est la valeur par défaut si vous omettez enctype.

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 .htmlfichier 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&#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 mis la valeur de texte par défaut a&#x03C9;b, ce qui signifie aωbque ωest U+03C9, qui sont les octets 61 CF 89 62en 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, ncBSD 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ωben 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=---------------------------735323031399963166993862150définit le type de contenu sur multipart/form-dataet indique que les champs sont séparés par la boundarychaîne donnée .

    Mais notez que:

    boundary=---------------------------735323031399963166993862150

    a deux papas de moins --que la barrière réelle

    -----------------------------735323031399963166993862150

    En effet, la norme exige 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 d'une demande à l'autre.

    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 enctypeen 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. 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 aiment aet bont été envoyés dans un octet, tandis que ceux non imprimables aiment 0xCFet 0x89ont 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.


3
@ Khanna111 %CFest de 3 octets: %, Cet F:-) histoire de le rendre lisible par l' homme.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

6
Sous OS X, ncn'acceptera pas à la fois -lles -parguments et les arguments. Mais cela fonctionne pour moi: while true; do printf '' | nc -l 8000; done.
PhilipS

4
Un petit mais important point non mentionné est que la limite spécifiée dans le Content-Typea deux tirets ( --) de moins, c'est-à-dire lorsque vous utilisez réellement la limite dans le corps du message, vous devez la préfixer avec --. De plus, la dernière limite doit être suffixée --, mais c'est assez facile à remarquer. Voir stackoverflow.com/questions/3508252/…
Bernard

1
Pour autant que je sache, le point de mettre des tirets dans la limite est de rendre impossible de vérifier la syntaxe de la demande à l'œil nu. Veuillez ne pas les utiliser dans vos jetons de limite.
Dewi Morgan

1
@DewiMorgan Vous avez tout à fait raison. J'ai édité le post et supprimé les tirets de la chaîne de limite.
Max

91

enctype='multipart/form-dataest un type d'encodage qui permet d'envoyer des fichiers via un POST . Tout simplement, sans cet encodage, 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 ce type de code .


Alors .. si le fichier n'est pas un fichier binaire, alors pouvons-nous travailler sans cela?
Yugal Jindle

D'après ce que je comprends, vous pouvez utiliser multipart/form-datapour envoyer des fichiers non binaires mais c'est inefficace. Je pense que l'utilisation application/x-www-form-urlencodedest la bonne façon d'envoyer des données non binaires, mais quelqu'un qui a plus d'expérience avec les fichiers non binaires peut avoir besoin de me corriger.
Matt Asbury

11
Le principal avantage de l'utilisation multipart/form-datapour l'envoi d'un fichier est qu'il fonctionnera automatiquement à la fois en frontend et en backend. Vous n'avez pas à faire de manipulation particulière. Tous les fichiers sont binaires même s'ils ne doivent contenir que du texte. application/x-www-form-urlencodedest le moyen standard de publier un formulaire sans fichiers joints. multipart/form-dataest le moyen standard de POSTER un formulaire avec des fichiers joints. (Il existe également de nombreux autres encodages, tels que application/jsonet application/json-patch+json, qui sont communs pour la communication entre le serveur et le client.)
Daniel Luna

6
Il vaut la peine de souligner que vous pouvez coder en base64 votre image et l'envoyer en tant que données de chaîne simples.
James

3
Suite au commentaire de @ Prospero ci-dessus: vous pouvez absolument envoyer des fichiers via POST sans utiliser multipart/form-data. Ce que vous ne pouvez pas faire, c'est utiliser une soumission de formulaire HTML ordinaire, sans JavaScript. La définition d'un formulaire à utiliser multipart/form-dataest le seul mécanisme fourni par HTML pour vous permettre de POSTER des fichiers sans utiliser JavaScript. J'ai l'impression que ce n'est pas assez clair dans la réponse, et qu'un lecteur naïf pourrait penser que l'impossibilité d'envoyer des fichiers sans multipart/form-dataest une limitation de HTTP ; ce n'est pas le cas.
Mark Amery

81

Lorsque vous soumettez un formulaire, vous dites à votre navigateur d'envoyer, via le protocole HTTP, un message sur le réseau, correctement enveloppé dans une structure de message de protocole TCP / IP. Une page HTML a un moyen d'envoyer des données au serveur: en utilisant <form>s.

Lorsqu'un formulaire est soumis, une requête HTTP est créée et envoyée au serveur, le message contiendra les noms de champs dans le formulaire et les valeurs renseignées par l'utilisateur. Cette transmission peut se produire avec des méthodesPOST ou GET HTTP .

  • POST indique à votre navigateur de créer un message HTTP et de mettre tout le contenu dans le corps du message (une manière très utile de faire les choses, plus sûre et aussi flexible).
  • GETsoumettra les données du formulaire dans la chaîne de requête . Il a quelques contraintes sur la représentation et la longueur des données.

Indiquer comment envoyer votre formulaire au serveur

L'attribut enctypen'a de sens que lors de l'utilisation de la POSTméthode. Lorsqu'il est spécifié, il demande au navigateur d'envoyer le formulaire en encodant 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 valeurs sont collectés et le 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 a un contrôle de téléchargement de fichier. Vous voulez envoyer le fichier binaire et cela garantit que le train de bits n'est pas modifié.
  • text/plain: Les espaces sont convertis, mais plus aucun encodage n'est effectué.

Sécurité

Lors de la soumission de formulaires, des problèmes de sécurité peuvent survenir, comme indiqué dans la RFC 7578 Section 7: Données de formulaire en plusieurs parties - Considérations de sécurité :

Tous les logiciels de traitement des formulaires doivent traiter les données de formulaire fournies par l'utilisateur
avec sensibilité, car elles contiennent souvent des informations confidentielles ou d'
identification personnelle . Il existe une utilisation répandue des fonctionnalités de «remplissage automatique» des formulaires dans les navigateurs Web; ceux-ci peuvent être utilisés pour inciter les utilisateurs à
envoyer sans le savoir des informations confidentielles lors de l'exécution de
tâches autrement inoffensives. multipart / form-data ne fournit aucune fonctionnalité
pour vérifier l'intégrité, garantir la confidentialité, éviter la
confusion des utilisateurs ou d'autres fonctionnalités de sécurité; ces préoccupations doivent être
traitées par les applications de remplissage de formulaires et d'interprétation de données de formulaires.

Les candidatures qui reçoivent des formulaires et les traitent doivent veiller à ne pas renvoyer au site de traitement des formulaires demandeur des données qui n'étaient pas destinées à être envoyées.

Il est important lors de l'interprétation du nom de fichier du
champ d'en-tête Content- Disposition de ne pas écraser par inadvertance des fichiers dans l'
espace fichier du destinataire.

Cela vous concerne si vous êtes développeur et que votre serveur traitera les formulaires soumis par les utilisateurs qui pourraient finir par contenir des informations sensibles.


1
Les informations sur la sécurité après la dernière modification ne sont pas pertinentes pour la question de ce que enctypeje fais. Je sais que c'est littéralement de la multipart/form-dataRFC, mais néanmoins c'est un dépotoir arbitraire de considérations de sécurité sur la soumission de formulaires qui sont entièrement orthogonaux pour savoir si les données sont envoyées en tant que application/x-www-form-urlencodedou multipart/form-data.
Mark Amery

38

enctype='multipart/form-data'signifie qu'aucun caractère ne sera encodé. c'est pourquoi ce type est utilisé lors du téléchargement de fichiers sur le serveur. Est
donc multipart/form-datautilisé lorsqu'un formulaire nécessite le téléchargement de données binaires, comme le contenu d'un fichier


8

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 plus une pour le texte du corps du formulaire qui peut être envoyé avec elles.


Cela implique que cela POSTsera probablement suffisant pour soumettre un fichier via un formulaire et que l'ajout multipart/form-datan'est qu'un bonus d'une certaine manière vague. Ce n'est pas le cas. La plupart des fichiers devront absolument être utilisés multipart/form-data.
underscore_d

1
  • L'attribut enctype ( ENC ode TYPE ) spécifie comment les données de formulaire doivent être codées lors de leur soumission au serveur.
  • multipart / form-data est l'une des valeurs de l'attribut enctype, qui est utilisé dans l'élément de formulaire qui a un téléchargement de fichier. en plusieurs parties signifie que les données du formulaire sont divisées en plusieurs parties et envoyées au serveur.

5
Je crois que enctype ne représente pas le type de cryptage. Aucun chiffrement n'est impliqué à ce niveau. Ma supposition est soit le type de codage ou le type inclus. Mais ce n'est sûrement pas du type à chiffrement.
Yeo

1
Votre dernière puce ici sur <head>et <body>est hors de propos et déroutante.
Mark Amery

0

Habituellement, c'est lorsque vous avez un formulaire POST qui doit prendre un téléchargement de fichier en tant que données ... cela indiquera au serveur comment il codera les données transférées, dans ce cas, il ne sera pas codé 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 pdf


-3

L'attribut enctype spécifie comment les données de formulaire doivent être codées lors de leur soumission au serveur.

L'attribut enctype ne peut être utilisé que si method = "post".

Aucun caractère n'est codé. Cette valeur est requise lorsque vous utilisez des formulaires dotés d'un contrôle de téléchargement de fichiers

De W3Schools


2
Cette citation ne mentionne même pas multipart/form-data. C'est aussi assez peu clair; que signifie la phrase "Aucun caractère codé"? -1.
Mark Amery
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.