简体   繁体   English

PHP-使用CURL将图像文件上传到其他域

[英]PHP - Upload an image file to other domain with CURL

I have two domain, as example site1.loc and site2.loc . 我有两个域,例如site1.locsite2.loc In site1.loc i have a php form file like this: site1.loc中,我有一个php表单文件,如下所示:

<?php
$c_name = "";
$c_phone = "";

if($_SERVER['REQUEST_METHOD']=="POST"){

    $c_name = $_POST['c_name'];
    $c_phone = $_POST['c_phone'];
    $c_pic = $_FILES['c_pic']['name']; // Image file

        // submit target URL
        $url = 'http://site2.loc/handler.php';

        $fields = array(
           'field1'=>$c_name,
           'field2'=>$c_phone,
           'field3'=>$c_pic
        );

        $postvars='';
        $sep='';
        foreach($fields as $key=>$value) 
        { 
           $postvars.= $sep.urlencode($key).'='.urlencode($value); 
           $sep='&'; 
        }


        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_POST,count($fields));
        curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);

        //execute post
        $result = curl_exec($ch);

        if(curl_errno($ch)) {
            echo 'Error: ' . curl_error($ch);
        }
        else {
            echo $result;
        }

        //close connection
        curl_close($ch);

}


echo '
<form action="" method="post" enctype="multipart/form-data">
    Name : <input type="text" name="c_name" value="'.$c_name.'" /> <br />
    Phone : <input type="text" name="c_phone" value="'.$c_phone.'" /> <br />
    Image : <input type="file" name="c_pic" /> <br />
    <input type="submit" />
</form>
    ';
?>

and handler.php in site2.loc like this: handler.php在这样site2.loc:

<?php
ob_start();
if (!isset($_SESSION)) { session_start(); }

    // CONNECT TO DB
    $db_con = mysql_connect("localhost", "root", "root");// or die("Could not connect to db.");
    if(!mysql_select_db("site2",$db_con)) die("No database selected.");

    // POST
    if(isset($_POST)){
        $c_name = $_POST['field1'];
        $c_phone = $_POST['field2'];    
        $c_pic = $_POST['field3'];  

        // UPLOAD FILE
        /* UPLOAD IMAGE CODE HERE */

        // INSERT TO DB
        if(mysql_query("INSERT INTO kontak (nama, telpon) VALUES ('$c_name','$c_phone')")){
            echo "INSERT SUCCESS";
        } else {
            echo "INSERT FAILED";
        }
    }

?>

This script runs well for storing the data to the database, but can not for upload an image file. 该脚本可以很好地运行以将数据存储到数据库,但不能用于上传图像文件。 Can anybody help me modify scripts above in order to upload an image file? 有人可以帮我修改上面的脚本以上传图像文件吗?

Thanks before. 之前谢谢。

No code in this answer, just a work flow example that will bypass curl : 这个答案中没有代码,只有一个绕过curl的工作流程示例:

  1. User posts a form with the uploaded file to "site 1", as per normal. 用户通常将带有上传文件的表单发布到“站点1”。
  2. "site 1" processes the form and the uploaded file. “站点1”处理表单和上载的文件。 The file is placed in a temp directory which is web accessible. 该文件放置在可通过Web访问的临时目录中。
  3. On "site 1", once the uploaded file has been checked, make a file_get_contents('http://site2.loc/pullfile.php?f=filename&sec=checkcode') call. 在“站点1”上,一旦检查了上载的文件,请进行file_get_contents('http://site2.loc/pullfile.php?f=filename&sec=checkcode')调用。 The contents of pullfile.php will do just that, pull the file from "site 1" to "site 2". pullfile.php的内容pullfile.php可以做到,将文件从“站点1”拉到“站点2”。
  4. The return from file_get_contents() can be checked for an error return from the "site 2" pullfile.php and on error, deal with it. 可以检查从file_get_contents()返回的内容是否存在从“ site 2” pullfile.php返回的错误,并且在出错时进行处理。 No error, remove the temp file. 没错,删除临时文件。
  5. The &sec=checkcode could be used to confirm the file has been uploaded successfully to "site 2". &sec=checkcode可用于确认文件已成功上传到“站点2”。 It could be an MD5 of the file or something else you come up with. 它可能是文件的MD5或您提出的其他内容。

Just an idea. 只是一个主意。

Edit : Some sample code to help make things clearer, maybe :] 编辑 :一些示例代码可以使事情变得更清晰,也许:]

// ---- Site 1, formprocess.php ----

// Your form processing goes here, including
// saving the uploaded file to a temp dir.

// Once the uploaded file is checked for errors, 
// you need move it to a known temp folder called 
// 'tmp'.

// this is the uploaded file name (which you would
// have got from the processed form data in $_FILES
// For this sample code, it is simple hard-coded.
$site1File = 'test.jpg';

$site1FileMd5 = md5_file('./tmp/'.$site1File);

// now make a remote request to "site 2"
$site2Result = file_get_contents('http://'.SITE_2_URL.'/pullfile.php?f='.$site1File.'&md5='.$site1FileMd5);

if ($site2Result == 'done') {
    unlink('./tmp/'.$site1File);
} else {
    echo '<p>
         Uploaded file failed to transfer to '.SITE_2_URL.'
          - but will be dealt with later.
         </p>';
}

And this will be the 'pullfile.php' on site 2 这将是站点2上的“ pullfile.php”

// ----- Site 2, pullfile.php -----

// This script will pull a file from site 1 and
// place it in '/uploaded'

// used to cross-check the uploaded file
$fileMd5 = $_GET['md5'];
$fileName = basename($_GET['f']);

// we need to pull the file from the './tmp/' dir on site 1
$pulledFile = file_get_contents('http://'.SITE_1_URL.'/tmp/'.$fileName);

// save that file to disk
$result = file_put_contents('./uploaded/'.$fileName,$pulledFile);
if (! $result) {
    echo 'Error: problem writing file to disk';
    exit;
}

$pulledMd5 = md5_file('./uploaded/'.$fileName);
if ($pulledMd5 != $fileMd5) {
    echo 'Error: md5 mis-match';
    exit;
}

// At this point, everything should be right.
// We pass back 'done' to site 1, so we know 
// everything went smooth. This way, a 'blank'
// return can be treated as an error too.
echo 'done';
exit;

CURLOPT_POSTFIELDS The full data to post in a HTTP "POST" operation. CURLOPT_POSTFIELDS要在HTTP“ POST”操作中发布的完整数据。 To post a file, prepend a filename with @ and use the full path. 要发布文件,请在文件名前添加@并使用完整路径。 This can either be passed as a urlencoded string like 'para1=va1&para2=val2&...' or as an array with the field name as key and field data as value. 可以将其作为诸如“ para1 = va1&para2 = val2&...”之类的urlencoded字符串或以字段名称作为键并将字段数据作为值的数组传递。 If value is an array, the Content-Type header will be set to multipart/form-data. 如果value是一个数组,则Content-Type标头将设置为multipart / form-data。

http://php.net/manual/en/function.curl-setopt.php http://php.net/manual/en/function.curl-setopt.php

Code snippet: 程式码片段:

$postvars['file'] = '@full/path/to/file.jpg';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
curl_exec($ch);

The way you are doing it right now won't work because your server does not send the file to the remote server but the local filename (from the user). 您现在的操作方式将无法使用,因为您的服务器不会将文件发送到远程服务器,而是将本地文件名发送给远程服务器(来自用户)。 Also to transfer a file via CURL you need to add a '@' before the name. 另外,要通过CURL传输文件,您还需要在名称前添加“ @”。

$c_pic = '@'. $_FILES['c_pic']['tmp_name']

Then the remote script also has to get the file from the $_FILES variable and copy it somewhere with move_uploaded_file ( PHP.net ) 然后,远程脚本还必须从$ _FILES变量获取文件,然后使用move_uploaded_filePHP.net )将其复制到某个位置

Also a tip: check $_FILES['c_pic']['error'] before doing this to prevent uploading garbage to the remote server. 还有一个提示:在执行此操作之前,请检查$_FILES['c_pic']['error'] ,以防止将垃圾上传到远程服务器。

Curl upload files 卷曲上传文件

// data fields for POST request
$fields = array("f1"=>"value1", "another_field2"=>"anothervalue");

// files to upload
$filenames = array("/tmp/1.jpg", "/tmp/2.png");;

$files = array();
foreach ($filenames as $f){
   $files[$f] = file_get_contents($f);
}

// URL to upload to
$url = "http://example.com/upload";


// curl

$curl = curl_init();

$url_data = http_build_query($data);

$boundary = uniqid();
$delimiter = '-------------' . $boundary;

$post_data = build_data_files($boundary, $fields, $files);


curl_setopt_array($curl, array(
  CURLOPT_URL => $url,
  CURLOPT_RETURNTRANSFER => 1,
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  //CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POST => 1,
  CURLOPT_POSTFIELDS => $post_data,
  CURLOPT_HTTPHEADER => array(
    //"Authorization: Bearer $TOKEN",
    "Content-Type: multipart/form-data; boundary=" . $delimiter,
    "Content-Length: " . strlen($post_data)

  ),


));


//
$response = curl_exec($curl);

$info = curl_getinfo($curl);
//echo "code: ${info['http_code']}";

//print_r($info['request_header']);

var_dump($response);
$err = curl_error($curl);

echo "error";
var_dump($err);
curl_close($curl);




function build_data_files($boundary, $fields, $files){
    $data = '';
    $eol = "\r\n";

    $delimiter = '-------------' . $boundary;

    foreach ($fields as $name => $content) {
        $data .= "--" . $delimiter . $eol
            . 'Content-Disposition: form-data; name="' . $name . "\"".$eol.$eol
            . $content . $eol;
    }


    foreach ($files as $name => $content) {
        $data .= "--" . $delimiter . $eol
            . 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . $eol
            //. 'Content-Type: image/png'.$eol
            . 'Content-Transfer-Encoding: binary'.$eol
            ;

        $data .= $eol;
        $data .= $content . $eol;
    }
    $data .= "--" . $delimiter . "--".$eol;


    return $data;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM