Réponses:
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:
text/plain
.Lorsque vous écrivez du code côté client:
multipart/form-data
lorsque votre formulaire contient des <input type="file">
élémentsmultipart/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 celui exposé par le $_POST
superglobal 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-data
est 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/plain
est 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).
quand devrions-nous l'utiliser
La réponse de Quentin est juste: utilisez multipart/form-data
si le formulaire contient un téléchargement de fichier, et application/x-www-form-urlencoded
sinon, c'est la valeur par défaut si vous omettez enctype
.
Je vais:
Il existe trois possibilités pour enctype
:
application/x-www-form-urlencoded
multipart/form-data
(spécification indique RFC7578 )text/plain
. Ceci n'est "pas interprétable de manière fiable par ordinateur", donc il ne devrait jamais être utilisé en production, et nous n'irons pas plus loin.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:
nc -l
ou un serveur ECHO: serveur de test HTTP acceptant les requêtes GET / POSTEnregistrez 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.
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 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?
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. 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 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
:!
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.
%CF
est de 3 octets: %
, C
et F
:-) histoire de le rendre lisible par l' homme.
nc
n'acceptera pas à la fois -l
les -p
arguments et les arguments. Mais cela fonctionne pour moi: while true; do printf '' | nc -l 8000; done
.
Content-Type
a 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/…
enctype='multipart/form-data
est 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 .
multipart/form-data
pour envoyer des fichiers non binaires mais c'est inefficace. Je pense que l'utilisation application/x-www-form-urlencoded
est 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.
multipart/form-data
pour 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-urlencoded
est le moyen standard de publier un formulaire sans fichiers joints. multipart/form-data
est le moyen standard de POSTER un formulaire avec des fichiers joints. (Il existe également de nombreux autres encodages, tels que application/json
et application/json-patch+json
, qui sont communs pour la communication entre le serveur et le client.)
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-data
est 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-data
est une limitation de HTTP ; ce n'est pas le cas.
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).GET
soumettra 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.L'attribut enctype
n'a de sens que lors de l'utilisation de la POST
mé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é.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.
enctype
je fais. Je sais que c'est littéralement de la multipart/form-data
RFC, 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-urlencoded
ou multipart/form-data
.
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-data
utilisé lorsqu'un formulaire nécessite le téléchargement de données binaires, comme 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 plus une pour le texte du corps du formulaire qui peut être envoyé avec elles.
POST
sera probablement suffisant pour soumettre un fichier via un formulaire et que l'ajout multipart/form-data
n'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
.
<head>
et <body>
est hors de propos et déroutante.
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
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
multipart/form-data
. C'est aussi assez peu clair; que signifie la phrase "Aucun caractère codé"? -1.