Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - Upload an image file to other domain with CURL

I have two domain, as example site1.loc and site2.loc. In site1.loc i have a php form file like this:

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

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

like image 513
Fredy Avatar asked May 16 '13 09:05

Fredy


People also ask

How to do a file upload with PHP curl?

To do a file upload with PHP CURL, simply set CURL to do a POST and attach the file. That covers the basics, but let us walk through a simple example in this guide – Read on! ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything…

Why is curl_file_create not working in PHP?

This is because curl_file_create was only introduced to PHP in version 5.5. Using the function curl_file_create to create a CURLFile object that represents our file is the recommended method of uploading a file with cURL. If the function exists, you should use it. If curl_file_exists does not exist.

What is the difference between $url and $uploadfieldname?

$url: This is the HTTP URL that you want to upload your file to. $uploadFieldName: This is the name of the POST field that will contain the file that you want cURL to upload.

What does the curl symbol mean when uploading files?

This symbol tells cURL that it is a file name and that it should post the data without any extra processing. If we are using the older method of uploading files with cURL, we also have to make sure that we disable the CURLOPT_SAFE_UPLOAD option.


2 Answers

No code in this answer, just a work flow example that will bypass curl:

  1. User posts a form with the uploaded file to "site 1", as per normal.
  2. "site 1" processes the form and the uploaded file. The file is placed in a temp directory which is web accessible.
  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. The contents of pullfile.php will do just that, pull the file from "site 1" to "site 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. No error, remove the temp file.
  5. The &sec=checkcode could be used to confirm the file has been uploaded successfully to "site 2". It could be an MD5 of the file or something else you come up with.

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

// ----- 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;
like image 194
Tigger Avatar answered Oct 24 '22 18:10

Tigger


CURLOPT_POSTFIELDS The full data to post in a HTTP "POST" operation. 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. If value is an array, the Content-Type header will be set to multipart/form-data.

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);
like image 28
Kristian Vitozev Avatar answered Oct 24 '22 16:10

Kristian Vitozev