Отправить файл через cURL из формы POST в PHP - PullRequest
41 голосов
/ 19 ноября 2010

Я пишу API и хочу обработать загрузку файлов из формы POST. Разметка для формы не слишком сложная:

<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>

Однако у меня возникают трудности с пониманием того, как обрабатывать эту серверную часть и отправлять вместе с запросом cURL.

Я знаком с отправкой POST запросов с помощью cURL с массивом данных, и ресурсы, которые я прочитал при загрузке файлов, говорят мне префикс имени файла с символом @. Но эти же ресурсы имеют жестко запрограммированное имя файла, например,

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

Ну и какой это путь к файлу? Где бы я найти это? Будет ли это что-то вроде $_FILES['image']['tmp_name'], и в этом случае мой массив $post должен выглядеть так:

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

Или я поступаю неправильно? Любой совет будет наиболее ценным.

РЕДАКТИРОВАТЬ: Если бы кто-то мог дать мне фрагмент кода, где я буду идти со следующими фрагментами кода, то я был бы очень признателен. Я в основном после того, что я отправил бы в качестве параметров cURL, и пример того, как использовать эти параметры с принимающим скриптом (давайте назовем его curl_receiver.php для аргумента).

У меня есть эта веб-форма:

<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>

И это будет 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']
}

Ответы [ 8 ]

56 голосов
/ 30 ноября 2010

Вот некоторый производственный код, который отправляет файл на FTP (может быть хорошим решением для вас):

// 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@email.org: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);
44 голосов
/ 18 марта 2015

Для людей, которые находят этот пост и используют PHP5.5 + , это может помочь.

Я обнаружил, что предложенный netcoder подход не работает.то есть это не сработало:

$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);

Я бы получил в $_POST var поле 'uploaded_file' - и ничего в $_FILES var.

Оказывается, чтодля php5.5 + есть новая curl_file_create() функция, которую вам нужно использовать.Таким образом, вышеприведенное станет:

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

Поскольку формат @ устарел.

26 голосов
/ 24 ноября 2010

Это должно работать:

$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);

В получающем скрипте вы должны иметь:

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
        )
     )
*/

Затем, если вы хотите правильно обработать загрузку файла, вы должны сделать что-то вроде этого:

if (move_uploaded_file($_FILES['uploaded_file'], '/path/to/destination/file.zip')) {
   // do stuff
}
10 голосов
/ 05 февраля 2016

Для моего символа @ не сработало, поэтому я провел некоторое исследование и нашел этот способ, и он работает для меня, надеюсь, это поможет вам.

    $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 голосов
/ 01 июля 2017

Это работает для меня при отправке вложения на Mercadolibre через систему обмена сообщениями.

Ответ 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;
}   
1 голос
/ 11 мая 2017

Объект файла cURL в процедурном методе:

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

Объект файла cURL в методе 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);
0 голосов
/ 02 ноября 2017

мы можем загрузить файл изображения по запросу скручивания, преобразовав его в строку base64. Итак, в посте мы отправим строку файла и затем закроем это в изображение.*

if(isset($_POST['image'])){
    $curlUrl='localhost/curlfile.php';  
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL, $curlUrl);
    curl_setopt($ch,CURLOPT_POST, 1);
    curl_setopt($ch,CURLOPT_POSTFIELDS, 'image='.$_POST['image']);
    $result = curl_exec($ch);
    curl_close($ch);
}

см. Здесь http://technoblogs.co.in/blog/How-to-upload-an-image-by-using-php-curl-request/118

0 голосов
/ 22 апреля 2014

Вот мое решение, я читал много постов, и они были очень полезны, в конце концов, я создаю код для небольших файлов, с помощью cUrl и Php, что я считаю его действительно полезным.

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

}

С этим мы должны попасть на "api.endpoint.post", в котором размещены следующие переменные Вы можете легко протестировать этот скрипт, и вы должны получить эти отладки для функции postFile () в последней строке

print_r ($ ответа); // распечатать ответ

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

Здесь вы должны хорошо работать, могли бы быть лучшие решения, но это работает и действительно полезно понять, как работает Mime Boundary и multipart / from-data в библиотеке php и curl

Мои наилучшие пожелания,

мои извинения за мой английский, но это не мой родной язык.

...