Sending multi-dimensional data and multiple files with CurlFile in one request

suggest change

Let’s say we have a form like the one below. We want to send the data to our webserver via AJAX and from there to a script running on an external server.

So we have normal inputs, a multi-select field and a file dropzone where we can upload multiple files.

Assuming the AJAX POST request was successful we get the following data on PHP site:

// print_r($_POST)

Array
(
    [first_name] => John
    [last_name] => Doe
    [activities] => Array
        (
            [0] => soccer
            [1] => hiking
        )
)

and the files should look like this

// print_r($_FILES)

Array
(
    [upload] => Array
        (
            [name] => Array
                (
                    [0] => my_photo.jpg
                    [1] => my_life.pdf
                )

            [type] => Array
                (
                    [0] => image/jpg
                    [1] => application/pdf
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/phpW5spji
                    [1] => /tmp/phpWgnUeY
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )

            [size] => Array
                (
                    [0] => 647548
                    [1] => 643223
                )

        )

)

So far, so good. Now we want to send this data and files to the external server using cURL with the CurlFile Class

Since cURL only accepts a simple but not a multi-dimensional array, we have to flatten the $_POST array first.

To do this, you could use this function for example which gives you the following:

// print_r($new_post_array)

Array
(
    [first_name] => John
    [last_name] => Doe
    [activities[0]] => soccer
    [activities[1]] => hiking
)

The next step is to create CurlFile Objects for the uploaded files. This is done by the following loop:

$files = array();

foreach ($_FILES["upload"]["error"] as $key => $error) {
    if ($error == UPLOAD_ERR_OK) {

        $files["upload[$key]"] = curl_file_create(
            $_FILES['upload']['tmp_name'][$key],
            $_FILES['upload']['type'][$key],
            $_FILES['upload']['name'][$key]
        );
    }
}

curl_file_create is a helper function of the CurlFile Class and creates the CurlFile objects. We save each object in the $files array with keys named “upload[0]” and “upload[1]” for our two files.

We now have to combine the flattened post array and the files array and save it as $data like this:

$data = $new_post_array + $files;

The last step is to send the cURL request:

$ch = curl_init();

curl_setopt_array($ch, array(
    CURLOPT_POST => 1,
    CURLOPT_URL => "https://api.externalserver.com/upload.php",
    CURLOPT_RETURNTRANSFER => 1,
    CURLINFO_HEADER_OUT => 1,
    CURLOPT_POSTFIELDS => $data
));

$result = curl_exec($ch);

curl_close ($ch);

Since $data is now a simple (flat) array, cURL automatically sends this POST request with Content Type: multipart/form-data

In upload.php on the external server you can now get the post data and files with $_POST and $_FILES as you would normally do.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


cURL:
* Sending multi-dimensional data and multiple files with CurlFile in one request

Table Of Contents
2 Arrays
4 Types
10 Cookies
14 JSON
15 SOAP
17 cURL
19 XML
21 Traits
35 UTF-8
36 URLs
38 PHPDoc
41 Loops
44 Closur
72 YAML
77 Cache
78 Streams
81 PDO
82 SQLite3
83 Sockets
87 MongoDB
93 IMAP
94 Redis
95 Imagick
102 APCu
108 PSR