0

I'm trying to figure out for days how would it be possible if at all, to upload multiple files parallel using PHP.

given I have a class called Request with 2 methods register() and executeAll():

class Request
{
    protected $curlHandlers = [];
    protected $curlMultiHandle = null;

    public function register($url , $file = []) 
    {
        if (empty($file)) {
            return; 
        }

        // Register the curl multihandle only once.
        if (is_null($this->curlMultiHandle)) {
            $this->curlMultiHandle = curl_multi_init();
        }

        $curlHandler = curl_init($url);

        $options = [
            CURLOPT_ENCODING => 'gzip',
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => $file,
            CURLOPT_USERAGENT => 'Curl',
            CURLOPT_HTTPHEADER => [
                'Content-Type' => 'multipart/form-data; boundry=-------------'.uniqid()
            ]
        ];

        curl_setopt_array($curlHandler, $options);

        $this->curlHandlers[] = $curlHandler;
        curl_multi_add_handle($this->curlMultiHandle, $curlHandler);
    }

    public function executeAll() 
    {
        $responses = [];

        $running = null;

        do {
            curl_multi_exec($this->curlMultiHandle, $running);
        } while ($running > 0);

        foreach ($this->curlHandlers as $id => $handle) {
            $responses[$id] = curl_multi_getcontent($handle);
            curl_multi_remove_handle($this->curlMultiHandle, $handle);
        }

        curl_multi_close($this->curlMultiHandle);

        return $responses;
    }
}

$request = new Request;

// For this example I will keep it simple uploading only one file.
// that was posted using a regular HTML form multipart
$resource = $_FILES['file'];
$request->register('http://localhost/upload.php', $resource);

$responses = $request->executeAll(); // outputs an empty subset of array(1) { 0 => array(0) { } }

Problem:

Can't figure out why on upload.php (the script which is my endpoint url on the register method) $_FILES is always an empty array:

upload.php:

<?php

    var_dump($_FILES); // outputs an empty array(0) { }

Things I've already tried:

prefixing the data with @, like so:

    $options = [
        CURLOPT_ENCODING => 'gzip',
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => ['file' => '@'.$file['tmp_name']],
        CURLOPT_USERAGENT => 'Curl',
        CURLOPT_HTTPHEADER => [
            'Content-Type' => 'multipart/form-data; boundry=-------------'.uniqid()
        ]
    ];

That unfortunately did not work.

What am I doing wrong ?

how could I get the file resource stored in $_FILES global on the posted script (upload.php) ?

Further Debug Information:

on upload.php print_r the headers I get as response the following:

array(1) {
  [0]=>
  string(260) "Array
(
    [Host] => localhost
    [User-Agent] => Curl
    [Accept] => */*
    [Accept-Encoding] => gzip
    [Content-Length] => 1106
    [Content-Type] => multipart/form-data; boundary=------------------------966fdfac935d2bba
    [Expect] => 100-continue
 )
"
}

print_r($_POST) on upload.php gives the following response back:

array(1) {
  [0]=>
  string(290) "Array
(
    [name] => example-1.jpg
    [encrypted_name] => Nk9pN21IWExiT2VlNnpHU3JRRkZKZz09.jpg
    [type] => image/jpeg
    [extension] => jpg
    [tmp_name] => C:\xampp\tmp\php77D7.tmp
    [error] => 0
    [size] => 62473
    [encryption] => 1
    [success] => 
    [errorMessage] => 
)
"
}

I appreciate any answer.

Thanks,

Eden

1 Answer 1

0

Can't figure out why on upload.php (the script which is my endpoint url on the register method) $_FILES is always an empty array - your first problem is that you override libcurl's boundary string with your own, but you have curl generate the multipart/form-data body automatically, meaning curl generates another random boundary string, different from your own, in the actual request body, meaning the server won't be able to parse the files. remove the custom boundary string from the headers (curl will insert its own if you don't overwrite it). your second problem is that you're using $_FILES wrong, you need to extract the upload name if you wish to give it to curl, and you need to convert the filenames to CURLFile objects to have curl upload them for you. another problem is that your script will for no good reason use 100% cpu while executing the multi handle, you should add a curl_multi_select to prevent choking an entire cpu core. for how to handle $_FILES, see http://php.net/manual/en/features.file-upload.post-method.php , for how to use CURLFile, see http://php.net/manual/en/curlfile.construct.php and for how to use curl_multi_select, see http://php.net/manual/en/function.curl-multi-select.php

Sign up to request clarification or add additional context in comments.

2 Comments

thank you so much! I have figured out that the main problem was that I did not use CurlFile...found this post: stackoverflow.com/questions/21905942/…
in addition thanks for the tip using curl_multi_select, I will check that out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.