2012-10-01 3 views
272

Vorrei utilizzare cURL non solo per inviare parametri di dati nel POST HTTP ma anche per caricare file con un nome di modulo specifico. Come dovrei fare per farlo?Utilizzo di arricciatura per caricare i dati POST con i file

parametri

HTTP Post:

userid = 12345 filecomment = Questo è un file di immagine

HTTP di upload file: posizione File = /home/user1/Desktop/test.jpg Nome modulo per il file = immagine (corrispondono al $ _FILES [ 'immagine'] sul lato PHP)

ho pensato parte del comando cURL come segue:

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

Il problema che sto ottenendo è la seguente:

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

Il problema è che sto usando $ _FILES [ 'immagine'] per raccogliere i file nello script PHP.

Come regolare i miei comandi CURL di conseguenza?

+6

La domanda riguarda la versione CLI di 'curl', perché' php' nei tag? – Barmar

+1

rimosso [php] – evandrix

+1

Parte del post originale: "Il problema è che sto usando $ _FILES ['immagine'] per raccogliere i file nello script PHP." – thotheolh

risposta

444

È necessario utilizzare l'opzione -F:
-F/--form <name=content> Specify HTTP multipart POST data (H)

Prova questa:

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

Grazie. Ha funzionato: D – thotheolh

+1

Sono confuso dalla parte relativa alla codifica url del file.Ho caricato file JPG e PNG come questo senza modificarli, senza problemi –

+0

@DavidGelbart Hai ragione. La mia risposta iniziale ha fatto riferimento all'opzione '-d' per errore, che ha bisogno della codifica dell'URL di input. Avrei dovuto rimuoverlo quando ho aggiornato la risposta all'opzione' -F'. Grazie per averlo capito. – jimp

18

Ecco la mia soluzione, ho letto un sacco di posti e sono stati davvero utili. Alla fine ho scritto del codice per i file di piccole dimensioni, con cURL e PHP che penso sia davvero 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 

} 

Con questo dovremmo essere in "api.endpoint.post" i seguenti annunci pubblicati. Puoi facilmente testare con questo script, e dovresti ricevere questi debug sulla funzione postFile() nell'ultima riga.

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>"; 
} 

Dovrebbe funzionare bene, possono essere le soluzioni migliori, ma questo funziona ed è molto utile per capire come il mimo Boundary e multipart/da-dati funziona su PHP e cURL biblioteca.

+0

se hai bisogno di inviare file non codificato cambia questa riga $ BODY. = 'Content-Transfer-Encoding: multipart/form-data'. $ eol. $ EOL; // inseriamo l'ultimo contenuto e 2 $ eol, $ BODY. = file_get_contents ($ file_url). $ EOL; // scriviamo il contenuto del file Base64 e il $ eol per finire i dati, – Andreah

54

Facendo l'id utente come variabile del percorso (consigliato):

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "[email protected]" http://mysuperserver/media/1234/upload/ 

Facendo l'id utente come parte del modulo:

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "[email protected];userid=1234" http://mysuperserver/media/upload/ 
+9

usa -F non è necessario impostare '' '" Content-Type: multipart/form-data "' '' –

+5

Non ho potuto ottenere -F per funzionare correttamente con quel separatore punto e virgola che hai indicato. Invece, ho dovuto fornire due argomenti -F ridondanti. Come: -F "[email protected]" -F "userid = 1234" – robbpriestley

1

Ecco come uscire correttamente i nomi di file arbitrari di file caricati con bash:

#!/bin/bash 
set -eu 

f="$1" 
f=${f//\\/\\\\} 
f=${f//\"/\\\"} 
f=${f//;/\\;} 

curl --silent --form "[email protected]\"$f\"" "$2" 
3

se si sta caricando un file binario come csv , usa sotto il formato per caricare il file

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'