'Sending multiple files from php curl

I'm using curl to send data and files to a web service.

From the shell I execute something like this:

curl -X POST -i -F "file[][email protected]" -F "file[][email protected]" -F "g=GROUP" -F "o=Object" -F "m=Body." http://localhost/api/email.php

and the web service receives an array named "file":

Array
(
    [file] => Array
        (
            [name] => Array
                (
                    [0] => file1.png
                    [1] => file2.pdf
                )
            [type] => Array
                (
                    [0] => image/png
                    [1] => application/pdf
                )
            [tmp_name] => Array
                (
                    [0] => /tmp/php1SFdK3
                    [1] => /tmp/phpPmwL8p
                )
            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )
            [size] => Array
                (
                    [0] => 74040
                    [1] => 169090
                )
        )
)

If I call it from php with this code:

    $data = [
      "g" => "GROUP",
      "o" => "object",
      "m" => "body.",
      "file[]" => $curlfile1,
      "file[]" => $curlfile2,
    ];
    
    $options = array(
      CURLOPT_URL => 'http://localhost/api/email.php',
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => $data,
      CURLOPT_HEADERFUNCTION => "readHeader",
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_SSL_VERIFYPEER => false
    );
    $ch = curl_init();
    curl_setopt_array($ch, $options);
    $response = curl_exec($ch);
    curl_close($ch);

the web service receives only the second file:

Array
(
    [file] => Array
        (
            [name] => Array
                (
                    [0] => file2.pdf
                )
            [type] => Array
                (
                    [0] => application/pdf
                )
            [tmp_name] => Array
                (
                    [0] => /tmp/phpPmwL8p
                )
            [error] => Array
                (
                    [0] => 0
                )
            [size] => Array
                (
                    [0] => 169090
                )
        )
)

It works fine if I put the keys in the file array:

    $data = [
      "g" => "GROUP",
      "o" => "object",
      "m" => "body.",
      "file[0]" => $curlfile1,
      "file[1]" => $curlfile2,
    ];

Is there a syntax so that I can avoid to put the keys of the file array, like in the shell command?



Solution 1:[1]

it should have worked, but doesn't, someone should complain on the php bugtracker... seems the answer is no, there's no pretty way to do it.

with that said, you could make a preprosessor function to prettify it for you... eg

<?php

function postArrayFixer(&$data):void{
    $original_keys = array_keys($data);
    foreach($original_keys as $key){
        $val = $data[$key];
        if(is_iterable($val)){
            foreach($val as $inner_key=>$inner_val){
                $data[$key.'['.$inner_key.']']=$inner_val;
            }
            unset($data[$key]);
        }
    }
}

$curlfile1=new CURLFile();
$curlfile2=new CURLFile();
$data = [
  "g" => "GROUP",
  "o" => "object", 
  "m" => "body.",
  "files" => array($curlfile1, $curlfile2)
];

$data["files"][]=new CURLFile();
postArrayFixer($data);
var_export($data);

makes

array (
  'g' => 'GROUP',
  'o' => 'object',
  'm' => 'body.',
  'files[0]' =>
  CURLFile::__set_state(array(
     'name' => '',
     'mime' => '',
     'postname' => '',
  )),
  'files[1]' =>
  CURLFile::__set_state(array(
     'name' => '',
     'mime' => '',
     'postname' => '',
  )),
  'files[2]' =>
  CURLFile::__set_state(array(
     'name' => '',
     'mime' => '',
     'postname' => '',
  )),
)

but this should have been unnecessary, sigh

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hanshenrik