Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using cURL to do a stream (line by line) FILE UPLOAD via POST with MULTIPART/FORM-DATA

I want to upload a file to a PHP form on a remote server with a certain URL. The upload form is a file upload form (Multipart/form-data), and my script should take a local file, and send it to that form.

The files are somewhat large, but the form file size limit is 1GB, which is no problem. But what is more pressing is that, due to some circumstances, I have to send the file as a stream!

This means having the file read line by line and then somehow upload it without creating a temporary file to assign via CURLOPTS_POSTFILDS.

So in short:

  • I need to use the CURLOPTS_READFUNCTION (I think) to get the contents of the file line by line
  • the method has to be POST
  • this has to simulate a regular file upload on the remote server upload form (so I guess I'd need some sort of a dummy filename for that)

I have tried a lot of ways to do this but I have failed. I am very new to cURL, I have tried a lot of info from other StackOverflow questions and other forums to no avail.

I have come to the conclusion that it might not be possible, but as I said, I have little idea of what I'm doing so I need some info or guidelines from someone more experienced. So far I think that CURLOPT_INFILE and CURLOPT_READFUNCTION are only working with PUT method, but I have to use POST.

Sorry for the long question, I hope it makes sense. And thanks in advance for any help or info.

EDIT

Here is some code as suggested:

$fh = fopen('php://memory','rw');
fwrite( $fh, $content); //maybe write the contents to memory here?
rewind($fh);


$options = array(
    CURLOPT_RETURNTRANSFER  => true
    ,CURLOPT_SSL_VERIFYPEER => false
    ,CURLOPT_SSL_VERIFYHOST => 1
    ,CURLOPT_FOLLOWLOCATION => 0
    ,CURLOPT_HTTPHEADER     => array(
        'Content-type: multipart/form-data'
    )
    ,CURLOPT_INFILE         => $fh //I want to read the contents from this file
    ,CURLOPT_INFILESIZE     => sizeof($content)
);
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, 'remote_form_url_here');
    curl_setopt ($ch, CURLOPT_POST, true);
    $post = array(
         'userfile' => '@i_do_not_have_a_file_to_put_here;filename=myfile.txt'
    );
    curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt_array ($ch, $options);


    //have the reading occur line by line when making the infile
    curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $fd, $length) use ($fh) {
    $line = fgets($fh);
    if ($line !== false) return $line; else return false;
    });


    $response = curl_exec($ch);

    echo $response;
    fclose($fh);

This code is mostly assembled from answers found around, but the parts that use the file handler do not seem to fit. I want to use a file handler, but it seems that if there is no way to confuse the form into thinking that the contents are a file and to pass some random file name.

This code does not even work (won't get to post the form at all), or some variations of it even show forbidden as a result.

Just for reference this is the test form I'm using to emulate the real situation i'm in until i make it work (don't want to send a ton of requests to the real server):

<form enctype="multipart/form-data" action="up.php" method="POST">


                Send this file: <input name="userfile" type="file" />
                    <input type="submit" value="Send File" />
            </form> 

And this is the behind code:

$target_path = "./ups/";

$target_path = $target_path . basename( $_FILES['userfile']['name']); 

if(move_uploaded_file($_FILES['userfile']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['userfile']['name']). 
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}

var_dump($_FILES['userfile']);
like image 361
todoubled Avatar asked Nov 13 '22 03:11

todoubled


1 Answers

If it works OK in the browser, you may use chrome dev tools. On Network Tab, find the post request. Right click -> Copy as cURL .

like image 181
enapupe Avatar answered Nov 14 '22 21:11

enapupe