266 votes

Quelle est la bonne façon de POST multipart/form-data en utilisant curl ?

J'ai utilisé cette syntaxe pour envoyer un fichier accompagné de quelques paramètres :

curl -v -include --form "key1=value1" --form upload=localfilename URL

Le fichier a une taille d'environ 500K. Tout d'abord, je constate que la longueur du contenu est de 254 du côté de la transmission. Plus tard, la longueur du contenu de la réponse du serveur est de 0. Où est-ce que je me trompe ?

Voici la trace complète de la commande.

* Couldn't find host xxx.xxx.xxx.xxx in the _netrc file; using defaults
* About to connect() to xxx.xxx.xxx.xxx port yyyy (#0)
*   Trying xxx.xxx.xxx.xxx...
* Adding handle: conn: 0x4b96a0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x4b96a0) send_pipe: 1, recv_pipe: 0
* Connected to xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx) port yyyy (#0)
* POST /zzzzzz/UploadFile HTTP/1.1
* User-Agent: curl/7.32.0
* Host: xxx.xxx.xxx.xxx:yyyy
* Accept: */*
* Content-Length: 254
* Expect: 100-continue
* Content-Type: multipart/form-data; boundary=------------------------948a6137eef50079
*
* HTTP/1.1 100 Continue
* HTTP/1.1 100 Continue

* HTTP/1.1 200 OK
* HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
* Server: Apache-Coyote/1.1
* Server: Apache-Coyote/1.1
* Added cookie JSESSIONID="C1D7DD042E250211D9DEA82688876F88" for domain xxx.xxx.xxx.xxx, path /zzzzz/, expire 0
* Set-Cookie: JSESSIONID=C1D7DD042E250211D9DEA82688876F88; Path=/zzzzzz/;
* HttpOnly
* Set-Cookie: JSESSIONID=C1D7DD042E250211D9DEA82688876F88; Path=/zzzzzz/; HttpOnly
* Content-Type: text/html;charset=ISO-8859-1
Content-Type: text/html;charset=ISO-8859-1
* Content-Length: 0
* Content-Length: 0
* Date: Tue, 01 Oct 2013 11:54:24 GMT
* Date: Tue, 01 Oct 2013 11:54:24 GMT
* Connection #0 to host xxx.xxx.xxx.xxx left intact

389voto

Kamalakshi Points 6868

La syntaxe suivante corrige le problème :

curl -v -F key1=value1 -F upload=@localfilename URL

32voto

Smac89 Points 1926

Voici ce qui a fonctionné pour moi

curl --form file='@filename' URL

Il semble que lorsque j'ai donné cette réponse ( Il y a plus de 4 ans ), je n'ai pas vraiment compris la question, ni le fonctionnement des champs de formulaire. J'ai simplement répondu en me basant sur ce que j'avais essayé dans un scénario différent, et cela a fonctionné pour moi.

Tout d'abord, la seule erreur commise par l'OP a été de ne pas utiliser la fonction @ avant le nom du fichier. Deuxièmement, ma réponse qui utilise file=... n'a fonctionné pour moi que parce que le champ du formulaire pour lequel j'essayais d'effectuer le téléchargement s'appelait file . Si votre champ de formulaire porte un autre nom, utilisez-le à la place.

Explication

A partir de la curl pages de manuel ; sous la description de l'option --form il est dit :

Cela permet de télécharger des fichiers binaires, etc. Pour forcer la partie "contenu" à être un fichier, préférez le nom du fichier avec le signe @. à être un fichier, préfixez le nom du fichier par un signe @. Pour obtenir la partie "contenu" d'un fichier, préfixez le nom du fichier par le symbole <. La différence entre @ et < est donc que @ permet à un fichier joint au message sous forme de téléchargement de fichier, tandis que le symbole < permet de créer un champ de texte et d'en extraire simplement le contenu à partir d'un fichier. fichier.

Il est fort probable que si vous essayez de télécharger un formulaire, vous voudrez utiliser la fonction @ pour télécharger le fichier au lieu de < qui télécharge le fichier contenu du fichier.

Addendum

Je dois également ajouter qu'il faut être prudent lors de l'utilisation de l'option < car dans la plupart des shells Unix, < est le symbole de redirection d'entrée [qui, par coïncidence, fournira également le contenu du fichier donné à l'entrée standard de la commande du programme précédent < ] . Cela signifie que si vous n'échappez pas correctement ce symbole ou si vous ne le mettez pas entre guillemets, vous risquez de voir votre curl ne se comporte pas comme vous le souhaitez.

Dans le même ordre d'idées, je recommanderai également de citer la @ symbole.


Cette autre question peut également vous intéresser : application/x-www-form-urlencoded ou multipart/form-data ?

Je dis cela parce que curl offre d'autres moyens de télécharger un fichier, mais ils diffèrent par le type de contenu défini dans l'en-tête. Par exemple, le type --data offre un mécanisme similaire pour télécharger des fichiers en tant que données, mais utilise un type de contenu différent pour le téléchargement.

Enfin, c'est tout ce que je voulais dire à propos de cette réponse depuis qu'elle a commencé à recevoir plus de votes. J'espère que cela aidera à dissiper toute confusion, comme la différence entre cette réponse et celle de la acceptée répondre. Il n'y en a pas vraiment, si ce n'est cette explication.

29voto

Logan Scott Points 291

Pour télécharger un fichier à l'aide de curl sous Windows, j'ai constaté que le chemin d'accès nécessite des guillemets doubles échappés

par exemple

curl -v -F 'upload=@\"C:/myfile.txt\"' URL

4voto

Lusk116 Points 177

J'ai eu du mal à envoyer une requête HTTP PUT multipartite avec curl à un backend Java. J'ai simplement essayé

curl -X PUT URL \
   --header 'Content-Type: multipart/form-data; boundary=---------BOUNDARY' \
   --data-binary @file

et le contenu du fichier était

-----------BOUNDARY
Content-Disposition: form-data; name="name1"
Content-Type: application/xml;version=1.0;charset=UTF-8

<xml>content</xml>
-----------BOUNDARY
Content-Disposition: form-data; name="name2"
Content-Type: text/plain

content
-----------BOUNDARY--

mais j'ai toujours obtenu un message d'erreur indiquant que la frontière était incorrecte. Après avoir débogué le backend Java, j'ai découvert que l'implémentation Java ajoutait une fonction \r\n-- comme préfixe de la frontière, donc après avoir changé mon fichier d'entrée en

                          <-- here's the CRLF
-------------BOUNDARY       <-- added '--' at the beginning
...
-------------BOUNDARY       <-- added '--' at the beginning
...
-------------BOUNDARY--     <-- added '--' at the beginning

tout fonctionne bien !

tl;dr

Ajouter une nouvelle ligne (CRLF \r\n ) au début du contenu de la limite de la multipartie et -- au début des limites et réessayer.

Vous envoyez peut-être une demande à un backend Java qui a besoin de ces changements dans la frontière.

1voto

Matt Points 217

Sur Windows 10, curl 7.28.1 dans powershell, j'ai trouvé ce qui suit qui fonctionne pour moi :

$filePath = "c:\temp\dir with spaces\myfile.wav"
$curlPath = ("myfilename=@" + $filePath)
curl -v -F $curlPath URL

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X