Lorsque je soumets un formulaire simple comme celui-ci avec un fichier joint:
<form enctype="multipart/form-data" action="http://localhost:3000/upload?upload_progress_id=12344" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
Comment envoie-t-il le fichier en interne? Le fichier est-il envoyé en tant que partie du corps HTTP en tant que données? Dans les en-têtes de cette demande, je ne vois rien de lié au nom du fichier.
Je voudrais juste savoir le fonctionnement interne du HTTP lors de l'envoi d'un fichier.
http
file-upload
0xSina
la source
la source
MAX_FILE_SIZE
en PHP - à quoiRéponses:
Jetons un coup d'œil à ce qui se passe lorsque vous sélectionnez un fichier et soumettez votre formulaire (j'ai tronqué les en-têtes par souci de concision):
REMARQUE: chaque chaîne de limite doit être préfixée avec un extra
--
, tout comme à la fin de la dernière chaîne de limite. L'exemple ci-dessus comprend déjà cela, mais il peut être facile de le manquer. Voir le commentaire de @Andreas ci-dessous.Au lieu d'URL codant les paramètres du formulaire, les paramètres du formulaire (y compris les données du fichier) sont envoyés sous forme de sections dans un document en plusieurs parties dans le corps de la demande.
Dans l'exemple ci-dessus, vous pouvez voir l'entrée
MAX_FILE_SIZE
avec la valeur définie dans le formulaire, ainsi qu'une section contenant les données du fichier. Le nom du fichier fait partie de l'en-Content-Disposition
tête.Les détails complets sont ici .
la source
Le format est appelé
multipart/form-data
, comme demandé à: Que signifie enctype = 'multipart / form-data'?Je vais:
Références HTML5
Il existe trois possibilités pour
enctype
:x-www-urlencoded
multipart/form-data
(spécification pointe vers RFC2388 )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.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:
nc -l
ou un serveur ECHO: serveur de test HTTP acceptant les requêtes GET / POSTEnregistrez le formulaire dans un
.html
fichier minimal :Nous avons mis la valeur de texte par défaut
aωb
, ce qui signifieaωb
queω
estU+03C9
, qui sont les octets61 CF 89 62
en UTF-8.Créez des fichiers à télécharger:
Exécutez notre petit serveur d'écho:
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.multipart / form-data
Firefox a envoyé:
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 avecnc -l localhost 8000 | hd
, qui dit que les octets:ont été envoyés (
61
== 'a' et62
== 'b').Il est donc clair que:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
définit le type de contenu surmultipart/form-data
et indique que les champs sont séparés par laboundary
chaîne donnée .Mais notez que:
a deux papas de moins
--
que la barrière réelleEn effet, la norme requiert 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:chaque champ obtient des sous-en-têtes avant ses données:,
Content-Disposition: form-data;
le champname
, lefilename
, 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 entre les demandes.
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-sequencesContent-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
enctype
enapplication/x-www-form-urlencoded
, rechargez le navigateur et soumettez à nouveau.Firefox a envoyé:
De toute évidence, les données du fichier n'ont pas été envoyées, 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 habituels aiment
a
etb
ont été envoyés dans un octet, tandis que ceux non imprimables aiment0xCF
et0x89
ont 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.
la source
Content-Disposition
etContent-Type
mais comment gérer le «contenu»?Envoyer un fichier en tant que contenu binaire (téléchargement sans formulaire ni FormData)
Dans les réponses / exemples donnés, le fichier est (très probablement) téléchargé avec un formulaire HTML ou en utilisant l' API FormData . Le fichier n'est qu'une partie des données envoyées dans la demande, d'où l'en-
multipart/form-data
Content-Type
tête.Si vous souhaitez envoyer le fichier en tant que seul contenu, vous pouvez l'ajouter directement en tant que corps de la demande et définir l'en-
Content-Type
tête sur le type MIME du fichier que vous envoyez. Le nom du fichier peut être ajouté dans l'en-Content-Disposition
tête. Vous pouvez télécharger comme ceci:Si vous n'utilisez pas (ne voulez pas) de formulaires et que vous ne souhaitez télécharger qu'un seul fichier, c'est la manière la plus simple d'inclure votre fichier dans la demande.
la source
Content-Type
-tête.J'ai cet exemple de code Java:
et j'ai ce fichier test.html:
et enfin le fichier que j'utiliserai à des fins de test, nommé a.dat, a le contenu suivant:
si vous interprétez les octets ci-dessus comme des caractères ASCII ou UTF-8, ils représenteront en fait:
Exécutons donc notre code Java, ouvrons test.html dans notre navigateur préféré, téléchargez
a.dat
et soumettez le formulaire et voyez ce que notre serveur reçoit:Eh bien, je ne suis pas surpris de voir les caractères 9ie car nous avons dit à Java de les imprimer en les traitant comme des caractères UTF-8. Vous pouvez également choisir de les lire sous forme d'octets bruts.
est en fait le dernier en-tête HTTP ici. Après cela vient le corps HTTP, où les méta et le contenu du fichier que nous avons téléchargé peuvent être vus.
la source
http://www.tutorialspoint.com/http/http_messages.htm
la source