477 votes

Utilisation de cURL pour télécharger des données POST avec des fichiers

Je voudrais utiliser cURL pour non seulement envoyer des paramètres de données dans HTTP POST mais aussi pour télécharger des fichiers avec un nom de formulaire spécifique. Comment dois-je m'y prendre ?

Paramètres HTTP Post :

identifiant = 12345 filecomment = Ceci est un fichier image

Téléchargement de fichiers HTTP : Emplacement du fichier = /home/user1/Desktop/test.jpg Nom de formulaire pour le fichier = image (correspond au $_FILES['image'] du côté PHP)

J'ai compris une partie de la commande cURL comme suit :

curl -d "userid=1&filecomment=This is an image file" --data-binary @"/home/user1/Desktop/test.jpg" localhost/uploader.php

Le problème que je rencontre est le suivant :

Notice: Undefined index: image in /var/www/uploader.php

Le problème est que j'utilise $_FILES['image'] pour récupérer les fichiers dans le script de PHP.

Comment puis-je adapter mes commandes cURL en conséquence ?

731voto

jimp Points 5784

Vous devez utiliser le -F option :
-F/--form <name=content> Specify HTTP multipart POST data (H)

Essayez ça :

curl \
  -F "userid=1" \
  -F "filecomment=This is an image file" \
  -F "image=@/home/user1/Desktop/test.jpg" \
  localhost/uploader.php

1 votes

Je suis confus par la partie concernant le codage url du fichier. J'ai téléchargé des fichiers JPG et PNG de cette manière, sans les modifier, sans aucun problème.

1 votes

@DavidGelbart Vous avez raison. Ma réponse initiale faisait référence à la -d par erreur, qui nécessite que l'entrée soit encodée en URL. J'aurais dû supprimer cette option lorsque j'ai mis à jour la réponse à la question de l'utilisateur. -F option. Merci de l'avoir remarqué.

0 votes

J'essaie de faire la même chose, mais pour une raison quelconque, je n'arrive pas à envoyer les fichiers il est indiqué que le fichier n'est pas joint.

133voto

rick Points 996

Saisir l'identifiant de l'utilisateur comme variable de chemin (recommandé) :

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "data=@test.mp3" http://mysuperserver/media/1234/upload/

Capture de l'identifiant de l'utilisateur dans le cadre du formulaire :

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "data=@test.mp3;userid=1234" http://mysuperserver/media/upload/

ou :

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "data=@test.mp3" -F "userid=1234" http://mysuperserver/media/upload/

22voto

Libertese Points 11

Voici ma solution, j'ai lu beaucoup de messages et ils ont été très utiles. Finalement, j'ai écrit du code pour les petits fichiers, avec cURL et PHP, et je pense que c'est vraiment utile.

public function postFile()
{    
        $file_url = "test.txt";  //here is the file route, in this case is on same directory but you can set URL too like "http://examplewebsite.com/test.txt"
        $eol = "\r\n"; //default line-break for mime type
        $BOUNDARY = md5(time()); //random boundaryid, is a separator for each param on my post curl function
        $BODY=""; //init my curl body
        $BODY.= '--'.$BOUNDARY. $eol; //start param header
        $BODY .= 'Content-Disposition: form-data; name="sometext"' . $eol . $eol; // last Content with 2 $eol, in this case is only 1 content.
        $BODY .= "Some Data" . $eol;//param data in this case is a simple post data and 1 $eol for the end of the data
        $BODY.= '--'.$BOUNDARY. $eol; // start 2nd param,
        $BODY.= 'Content-Disposition: form-data; name="somefile"; filename="test.txt"'. $eol ; //first Content data for post file, remember you only put 1 when you are going to add more Contents, and 2 on the last, to close the Content Instance
        $BODY.= 'Content-Type: application/octet-stream' . $eol; //Same before row
        $BODY.= 'Content-Transfer-Encoding: base64' . $eol . $eol; // we put the last Content and 2 $eol,
        $BODY.= chunk_split(base64_encode(file_get_contents($file_url))) . $eol; // we write the Base64 File Content and the $eol to finish the data,
        $BODY.= '--'.$BOUNDARY .'--' . $eol. $eol; // we close the param and the post width "--" and 2 $eol at the end of our boundary header.

        $ch = curl_init(); //init curl
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                         'X_PARAM_TOKEN : 71e2cb8b-42b7-4bf0-b2e8-53fbd2f578f9' //custom header for my api validation you can get it from $_SERVER["HTTP_X_PARAM_TOKEN"] variable
                         ,"Content-Type: multipart/form-data; boundary=".$BOUNDARY) //setting our mime type for make it work on $_FILE variable
                    );
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); //setting our user agent
        curl_setopt($ch, CURLOPT_URL, "api.endpoint.post"); //setting our api post url
        curl_setopt($ch, CURLOPT_COOKIEJAR, $BOUNDARY.'.txt'); //saving cookies just in case we want
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // call return content
        curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); navigate the endpoint
        curl_setopt($ch, CURLOPT_POST, true); //set as post
        curl_setopt($ch, CURLOPT_POSTFIELDS, $BODY); // set our $BODY 

        $response = curl_exec($ch); // start curl navigation

     print_r($response); //print response

}

Avec cela nous devrions obtenir sur le "api.endpoint.post" les vars suivants affichés. Vous pouvez facilement tester avec ce script, et vous devriez recevoir ces débogages sur la fonction postFile() à la dernière rangée.

print_r($response); //print response

public function getPostFile()
{

    echo "\n\n_SERVER\n";
    echo "<pre>";
    print_r($_SERVER['HTTP_X_PARAM_TOKEN']);
    echo "/<pre>";
    echo "_POST\n";
    echo "<pre>";
    print_r($_POST['sometext']);
    echo "/<pre>";
    echo "_FILES\n";
    echo "<pre>";
    print_r($_FILEST['somefile']);
    echo "/<pre>";
}

Cela devrait bien fonctionner, il peut y avoir de meilleures solutions mais cela fonctionne et c'est vraiment utile pour comprendre comment le mime Boundary et multipart/from-data fonctionne sur PHP et la bibliothèque cURL.

0 votes

Si vous devez envoyer un fichier non codé, changez ces lignes $BODY.= 'Content-Transfer-Encoding : multipart/form-data' . $eol . $eol ; // nous mettons le dernier contenu et 2 $eol, $BODY.= file_get_contents($file_url) . $eol ; // nous écrivons le contenu du fichier Base64 et le $eol pour terminer les données,

21voto

KARTHIKEYAN.A Points 4408

Si vous téléchargez un fichier binaire tel que csv, utilisez le format suivant pour télécharger le fichier

curl -X POST \
    'http://localhost:8080/workers' \
    -H 'authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyIsInR5cGUiOiJhY2Nlc3MifQ.eyJ1c2VySWQiOjEsImFjY291bnRJZCI6MSwiaWF0IjoxNTExMzMwMzg5LCJleHAiOjE1MTM5MjIzODksImF1ZCI6Imh0dHBzOi8veW91cmRvbWFpbi5jb20iLCJpc3MiOiJmZWF0aGVycyIsInN1YiI6ImFub255bW91cyJ9.HWk7qJ0uK6SEi8qSeeB6-TGslDlZOTpG51U6kVi8nYc' \
    -H 'content-type: application/x-www-form-urlencoded' \
    --data-binary '@/home/limitless/Downloads/iRoute Masters - Workers.csv'

11voto

Evandro Points 926

Après de nombreux essais, cette commande a fonctionné pour moi :

curl -v -F filename=image.jpg -F upload=@image.jpg http://localhost:8080/api/upload

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