2012-10-01 185 views
272

Me gustaría utilizar cURL para no solo enviar parámetros de datos en HTTP POST sino también cargar archivos con nombre de formulario específico. ¿Cómo debo hacer eso?Uso de curl para cargar datos POST con archivos

parámetros

HTTP Post:

identificador de usuario = 12345 filecomment = Este es un archivo de imagen

carga de archivos HTTP: ubicación del archivo = /home/user1/Desktop/test.jpg Nombre del formulario para el archivo = imagen (corresponden a la $ _FILES [ 'imagen'] en el lado PHP)

pensé parte del comando cURL como sigue:

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

El problema que estoy recibiendo es el siguiente:

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

El problema es que estoy usando $ _FILES [ 'imagen'] para recoger archivos en el script PHP.

¿Cómo ajusto mis comandos cURL en consecuencia?

+6

La pregunta es acerca de la versión CLI de 'curl', ¿por qué es' php' en las etiquetas? – Barmar

+1

eliminado [php] – evandrix

+1

Parte de la publicación original: "El problema es que estoy usando $ _FILES ['image'] para recoger archivos en el script PHP." – thotheolh

Respuesta

444

Es necesario utilizar la opción -F:
-F/--form <name=content> Specify HTTP multipart POST data (H)

Prueba esto:

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

Gracias. Funcionó: D. – thotheolh

+1

Estoy confundido por la parte sobre la codificación url del archivo. He subido archivos JPG y PNG como este sin modificarlos, sin ningún problema. –

+0

@DavidGelbart Tienes razón. Mi respuesta inicial hizo referencia a la opción '-d' por error, que necesita la entrada URL-encoded. Debería haber eliminado eso cuando actualicé la respuesta a la opción' -F'. Gracias por captar eso. – jimp

18

Aquí está mi solución, he estado leyendo un montón de mensajes y fueron muy útiles. Finalmente escribí un código para archivos pequeños, con cURL y PHP que creo que es realmente útil.

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 esto deberíamos obtener en el "api.endpoint.post" los siguientes vars publicados. Puede probar fácilmente con este script, y debe recibir este debugs en la función postFile() en la última fila.

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

Debería funcionar bien, ellos pueden ser mejores soluciones, pero esto funciona y es muy útil para entender cómo el mimo de Límites y varias partes/de-datos trabaja en la biblioteca PHP y cURL.

+0

si necesita enviar un archivo no codificado, cambie estas líneas $ BODY. = 'Content-Transfer-Encoding: multipart/form-data'. $ eol. $ eol; // ponemos el último contenido y 2 $ eol, $ BODY. = file_get_contents ($ file_url). $ eol; // escribimos el contenido del archivo Base64 y el $ eol para terminar los datos, – Andreah

54

La captura de la identificación del usuario como variable de ruta (recomendado):

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

Atrapar el ID de usuario como parte de la forma:

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

uso -F no necesita establecer '' '" Content-Type: multipart/form-data "' '' –

+5

No pude obtener -F para que funcione correctamente con ese separador de punto y coma que indicó. En cambio, tuve que proporcionar dos argumentos F redundantes. Me gusta: -F "[email protected]" -F "userid = 1234" – robbpriestley

1

Aquí es cómo escapar correctamente los nombres de archivos arbitrarios de los archivos cargados con bash:

#!/bin/bash 
set -eu 

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

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

si está cargando un archivo binario como csv El uso por debajo formato de archivo para cargar

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' 
Cuestiones relacionadas