web-dev-qa-db-fra.com

Comment puis-je réécrire cette demande CURL multipart/form-data sans utiliser -F?

Comment puis-je réécrire la commande CURL suivante afin qu'elle n'utilise pas l'option -F, mais génère toujours la même requête HTTP exacte? c'est-à-dire qu'il passe directement les données multipart/form dans le corps.

curl -X POST -F example=test http://localhost:3000/test
29
William Denniss

Résolu:

curl \
  -X POST \
  -H "Content-Type: multipart/form-data; boundary=----------------------------4ebf00fbcf09" \
  --data-binary @test.txt \
  http://localhost:3000/test

test.txt contient le texte suivant et, plus important encore, CRLF (\ r\n) fins de ligne:

------------------------------4ebf00fbcf09
Content-Disposition: form-data; name="example"

test
------------------------------4ebf00fbcf09--

Remarques: il est important d’utiliser --data-binary au lieu de l’ancien -d, car l’ancien préserve les fins de ligne (qui sont très importantes). Notez également que la limite dans le corps commence par un -- supplémentaire.

Je vais le répéter parce que c'est très important, mais ce fichier de corps de demande doit avoir des fins de ligne CRLF. JEdit ( comment définir les fins de ligne dans jEdit ) est un éditeur de texte multi-plateforme avec un bon support de fin de ligne.

Si vous êtes intéressé par la façon dont j'ai résolu ce problème (débogage avec une application Ruby on Rails) et pas seulement la solution finale, j'ai écrit mes étapes de débogage sur mon blog .

58
William Denniss

Vous pouvez utiliser l'argument --form avec un 

curl -H "Content-Type: multipart/related" \
  --form "[email protected];type=image/jpeg" http://localhost:3000/test
21
mimming

Voici une autre réponse avec l’instruction CURL originale ré-écrite en utilisant -d comme une ligne, sans fichiers temporaires. Personnellement, j’estime que l’approche des fichiers temporaires est plus facile à comprendre, mais je mets ceci ici pour référence:

curl -X POST -H "Content-Type: multipart/form-data; boundary=----------------------------4ebf00fbcf09" -d $'------------------------------4ebf00fbcf09\r\nContent-Disposition: form-data; name="example"\r\n\r\ntest\r\n------------------------------4ebf00fbcf09--\r\n' http://localhost:3000/test

Notes: la syntaxe $'blar' est telle que bash analyse le\r\n comme un jeton CRLF. Merci à cette réponse pour ce conseil.

13
William Denniss

C’est ce que j’utilise, je pense que c’est propre et qu’il n’a pas besoin de fichiers temporaires, ni d’emballer RAM au cas où vous voudriez télécharger des fichiers entiers (donc pas de lecture de fichiers en mémoire).

# Set these two.
file='path/to/yourfile.ext'
url='http://endpoint.example.com/foo/bar'

delim="-----MultipartDelimeter$$$RANDOM$RANDOM$RANDOM"
nl=$'\r\n'
mime="$(file -b --mime-type "$file")"

# This is the "body" of the request.
data() {
    # Also make sure to set the fields you need.
    printf %s "--$delim${nl}Content-Disposition: form-data; name=\"userfile\"${nl}Content-Type: $mime$nl$nl"
    cat "$file"
    printf %s "$nl--$delim--$nl"
}

# You can later grep this, or something.
response="$(data | curl -# "$url" -H "content-type: multipart/form-data; boundary=$delim" --data-binary @-)"
2
Camilo Martin

Voici comment je le ferais:

curl https://httpbin.org/post \
    -H 'content-type: multipart/form-data; boundary=----FormBoundary123456789' \
    --data-binary $'------FormBoundary123456789\r
Content-Disposition: form-data; name="example"\r
\r
test\r
------FormBoundary123456789--\r
'

Ou un peu plus sophistiqué (devrait être portable pour la plupart des coquilles modernes):

DELIM=----FormBoundary$RANDOM$RANDOM

curl https://httpbin.org/post \
    -H "content-type: multipart/form-data; boundary=$DELIM" \
    --data-binary --$DELIM$'\r
Content-Disposition: form-data; name="example"\r
\r
test\r
'--$DELIM--$'\r
'
0
Eduardo

Ceci est pour télécharger un fichier image en utilisant "Content-Type: multipart/related",

curl --trace trace.txt -X POST -H 'Content-Type: multipart/related; boundary=boundary_1234' --data-binary $'--boundary_1234\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{\r\n\t"title": "TestFile"\r\n}\r\n\r\n--boundary_1234\r\nContent-Type: image/jpeg\r\n\r\n' --data-binary '@Image0177.jpg' --data-binary $'\r\n--boundary_1234--\r\n' 'http://localhost:3000/google/upload/drive/v2/files?uploadType=multipart'
0
Mohan R