web-dev-qa-db-fra.com

Envoyer le fichier via cURL à partir du formulaire POST in PHP

J'écris une API et je veux gérer les téléchargements de fichiers à partir d'un formulaire POST. Le balisage du formulaire n'est pas trop complexe:

<form action="" method="post" enctype="multipart/form-data">
  <fieldset>
    <input type="file" name="image" id="image" />
    <input type="submit" name="upload" value="Upload" />
  </fieldset>
</form>

Cependant, j'ai du mal à comprendre comment gérer ce côté serveur et envoyer avec une demande cURL.

Je suis habitué à envoyer des requêtes POST avec cURL avec un tableau de données, et les ressources que j'ai lues lors du téléchargement de fichiers me disent de préfixer le nom de fichier avec un @ symbole. Mais ces mêmes ressources ont un nom de fichier codé en dur, par exemple.

$post = array(
    'image' => '@/path/to/myfile.jpg',
    ...
);

Eh bien, quel chemin de fichier est-ce? Où le trouverais-je? Serait-ce quelque chose comme $_FILES['image']['tmp_name'], auquel cas mon $post le tableau devrait ressembler à ceci:

$post = array(
    'image' => '@' . $_FILES['image']['tmp_name'],
    ...
);

Ou est-ce que j'y vais mal? Tout conseil serait le plus apprécié.

EDIT: Si quelqu'un pouvait me donner un extrait de code de l'endroit où j'irais avec les extraits de code suivants, je serais très reconnaissant. Je suis principalement après ce que j'enverrais comme paramètres cURL, et un exemple de la façon d'utiliser ces paramètres avec le script de réception (appelons-le curl_receiver.php pour le bien de l'argument).

J'ai ce formulaire web:

<form action="script.php" method="post" enctype="multipart/form-data">
  <fieldset>
    <input type="file" name="image />
    <input type="submit" name="upload" value="Upload" />
  </fieldset>
</form>

Et ce serait script.php:

if (isset($_POST['upload'])) {
    // cURL call would go here
    // my tmp. file would be $_FILES['image']['tmp_name'], and
    // the filename would be $_FILES['image']['name']
}
42
Martin Bean

Voici un code de production qui envoie le fichier à un ftp (peut être une bonne solution pour vous):

// This is the entire file that was uploaded to a temp location.
$localFile = $_FILES[$fileKey]['tmp_name']; 

$fp = fopen($localFile, 'r');

// Connecting to website.
$ch = curl_init();

curl_setopt($ch, CURLOPT_USERPWD, "[email protected]:password");
curl_setopt($ch, CURLOPT_URL, 'ftp://@ftp.website.net/audio/' . $strFileName);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'CURL_callback');
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
curl_exec ($ch);

if (curl_errno($ch)) {

    $msg = curl_error($ch);
}
else {

    $msg = 'File uploaded successfully.';
}

curl_close ($ch);

$return = array('msg' => $msg);

echo json_encode($return);
57
Jeff Davis

Pour les personnes qui trouvent ce message et utilisent PHP5.5 +, cela pourrait aider.

Je trouvais que l'approche suggérée par netcoder ne fonctionnait pas. c'est-à-dire que cela n'a pas fonctionné:

$tmpfile = $_FILES['image']['tmp_name'];
$filename = basename($_FILES['image']['name']);
$data = array(
    'uploaded_file' => '@'.$tmpfile.';filename='.$filename,
);
$ch = curl_init();   
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

Je recevrais dans la variable $_POST Le champ 'uploaded_file' - et rien dans la var $_FILES.

Il s'avère que pour php5.5 + il y a une nouvelle fonction curl_file_create() que vous devez utiliser. Ainsi, ce qui précède deviendrait:

$data = array(
    'uploaded_file' => curl_file_create($tmpfile, $_FILES['image']['type'], $filename)
);

Le format @ Étant désormais obsolète.

44
CharlesA

Cela devrait fonctionner:

$tmpfile = $_FILES['image']['tmp_name'];
$filename = basename($_FILES['image']['name']);

$data = array(
    'uploaded_file' => '@'.$tmpfile.';filename='.$filename,
);

$ch = curl_init();   
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
// set your other cURL options here (url, etc.)

curl_exec($ch);

Dans le script de réception, vous auriez:

print_r($_FILES);
/* which would output something like
     Array (
        [uploaded_file] => Array (
            [tmp_name] => /tmp/f87453hf
            [name] => myimage.jpg
            [error] => 0
            [size] => 12345
            [type] => image/jpeg
        )
     )
*/

Ensuite, si vous souhaitez gérer correctement le téléchargement du fichier, vous feriez quelque chose comme ceci:

if (move_uploaded_file($_FILES['uploaded_file'], '/path/to/destination/file.Zip')) {
   // do stuff
}
26
netcoder

Pour moi, le symbole @ n'a pas fonctionné, alors je fais des recherches et j'ai trouvé cette méthode et cela fonctionne pour moi, j'espère que cela vous aidera.

    $target_url = "http://server:port/xxxxx.php";           
    $fname = 'file.txt';   
    $cfile = new CURLFile(realpath($fname));

        $post = array (
                  'file' => $cfile
                  );    

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $target_url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");   
    curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));
    curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);   
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);  
    curl_setopt($ch, CURLOPT_TIMEOUT, 100);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

    $result = curl_exec ($ch);

    if ($result === FALSE) {
        echo "Error sending" . $fname .  " " . curl_error($ch);
        curl_close ($ch);
    }else{
        curl_close ($ch);
        echo  "Result: " . $result;
    }   
10
Joacer

Cela fonctionne pour moi lors de l'envoi d'une pièce jointe à Mercadolibre, via son système de messagerie.

La réponse https://stackoverflow.com/a/35227055/7656744

$target_url = "http://server:port/xxxxx.php";           
$fname = 'file.txt';   
$cfile = new CURLFile(realpath($fname));

    $post = array (
              'file' => $cfile
              );    

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");   
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);   
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);  
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result = curl_exec ($ch);

if ($result === FALSE) {
    echo "Error sending" . $fname .  " " . curl_error($ch);
    curl_close ($ch);
}else{
    curl_close ($ch);
    echo  "Result: " . $result;
}   
3
otharwa

objet fichier cURL dans la méthode procédurale:

$file = curl_file_create('full path/filename','extension','filename');

objet fichier cURL dans la méthode Oop:

$file = new CURLFile('full path/filename','extension','filename');

$post= array('file' => $file);

$curl = curl_init();  
//curl_setopt ... 
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
1
lalithkumar