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

164

J'ai utilisé cette syntaxe pour publier un fichier avec quelques paramètres:

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

Le fichier mesure environ 500 Ko. Tout d'abord, je vois que la longueur du contenu est de 254 du côté émission. 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
Kamalakshi
la source
duplication possible de Utilisation de curl pour télécharger des données POST avec des fichiers
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

254

La syntaxe suivante le corrige pour vous:

curl -v -F key1=value1 -F upload=@localfilename URL
Kamalakshi
la source
qu'en est-il de Windows et curl.exe?
Piotr
1
qu'en est-il de plusieurs pièces jointes?
hellboy
8
Cela fonctionne exactement de la même manière sous Windows et il prend en charge plusieurs "pièces jointes" / fichiers: ajoutez simplement plus d'instances -F!
Daniel Stenberg
Cette réponse a un bon exemple de téléchargement de plusieurs fichiers. stackoverflow.com/questions/11599957/…
bmoran
Cela marche. sur curl, nous n'avons pas besoin d'ajouter quelque chose comme ceci:-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
Emily
19

pour télécharger un fichier en utilisant curl dans Windows, j'ai trouvé que le chemin nécessite des guillemets doubles échappés

par exemple

curl -v -F 'upload=@\"C:/myfile.txt\"' URL
Logan Scott
la source
1
Cette réponse m'a beaucoup aidé. Bien que dans mon cas je ne devrais pas m'échapper ", c'est dans mon cas sur Mac que je devrais l'envoyer comme curl -X POST -F key1=value1 -F 'image=@"/Users/ivkremer/Downloads/file name.jpg"';
ivkremer
dans mon cas - j'ai eu un transfert réussi sans aucune citation: curl -v -F file=@/Users/path/to/file/testq.jpg 192.168.0.101:8080/upload-image
chatlanin le
Dans mon cas sous Windows, je ne pouvais pas utiliser les guillemets simples et j'ai dû utiliser des guillemets doubles comme celui-cicurl -F "filename=@\"C:\temp\file.jpg\"" https://someurl.com
Beems
5

C'est ce qui a fonctionné pour moi

curl -F file=@filename URL
smac89
la source
1

J'ai eu du mal à envoyer une requête HTTP PUT en plusieurs parties avec curlun 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 eu une erreur indiquant que la limite était incorrecte. Après un débogage du backend Java, j'ai découvert que l'implémentation Java ajoutait un \r\n--comme préfixe à la limite, 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

Ajoutez une nouvelle ligne (CRLF \r\n) au début du contenu de la limite en plusieurs parties et --au début des limites et réessayez.

Peut-être que vous envoyez une demande à un backend Java qui a besoin de ces changements dans la limite.

Lusk116
la source
Lors de la copie de données POST avec la console Web Firefox, j'ai également remarqué qu'elle utilisait à la \nplace de \r\n. Même la copie mitmproxy que cURL utilisait \n, j'ai donc dû copier la requête brute avec mitmproxy. J'ai vu avec hexdump qu'il utilisait du code hexadécimal 0Aau lieu de 0D 0A.
baptx le
le \r\nest obligatoire. Regardez tools.ietf.org/html/rfc2046#section-5.1.1 page 19.
Adam Zahran
0

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

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