-1

I need to do the following using PHP curl:

curl "https://the.url.com/upload"
  -F file="@path/to/the/file"
  -F colours[]="red"
  -F colours[]="yellow"
  -F colours[]="blue"

The code I have tried:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
   'file' => curl_file_create($file),
   'colours' = ['red','yellow','blue']
]);
$response = curl_exec($ch);

But I just get an error 'Array to string conversion in... (the colours line)'. If I remove the colours entirely then it works but I need to include them.

I have tried putting the post fields array in http_build_query() but then the server returns '415 Unsupported Media Type'. I'm guessing because it's missing a mime type (the file is a custom binary file).

I have also tried...

'colours[1]' = 'red'
'colours[2]' = 'yellow'
'colours[2]' = 'blue'

But the server returns an error saying colours must be an array. It's as though I need to create an associative array but with duplicate keys... which I know I can't do.

Can anyone help?

Robin Fuller
  • 153
  • 2
  • 9
  • 1
    I recommend you to use this little tool https://incarnate.github.io/curl-to-php/ – executable Jun 28 '22 at 15:30
  • Maybe look at http_build_query – ADyson Jun 28 '22 at 15:30
  • @executable that's a really handy tool but unfortunately it produced code as ```['colours[]'=>'red', 'yellow[]'=>'red' ] ``` which isn't going to work. Plus file upload using @ prefix is no longer allowed in PHP – Robin Fuller Jun 28 '22 at 15:46

2 Answers2

0

From the document of CURLOPT_POSTFIELDS.

This parameter can either be passed as a urlencoded string like 'para1=val1&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.

The function http_build_query() will make the value becomes 'para1=val1&para2=val2&...'.

So, I use this as post fields value as array and it work.

$postFields['hidden-input[0]'] = 'hidden value (from cURL).';

In your case, it should be.

curl_setopt($ch, CURLOPT_POSTFIELDS, [
   'file' => curl_file_create($file),
   'colours[0]' => 'red',
   'colours[1]' => 'yellow',
   'colours[2]' => 'blue',
]);

Related answered: 1.
The manual array (name[0]) copied from PHP document in Example #2 CURLFile::__construct() uploading multiple files example.

vee
  • 4,506
  • 5
  • 44
  • 81
  • Thank you @vee that looks like it would normally work. However I get an error response from the server ```'Invalid parameter: 'colours' should be an array (use 'colours[]' instead)'```. I've no idea what the server is written in. It's not ours. – Robin Fuller Jun 29 '22 at 08:38
  • It actually is the same with HTML form `name="colours[]"`. If you tested with this HTML form and work, what I suggested should work. The number in indexed array should be start from zero and increase by one while in your question start from `1` and duplicated with `2`. – vee Jun 29 '22 at 11:56
0

While the answer from @vee should have worked, this came down to validation on this particular server application. After consulting with the vender, I ended up having to do this:

$headers = ['Content-type: multipart/form-data'];

$postFields = [
   // NEEDED TO INCLUDE THE MIME TYPE
   'file' => curl_file_create($file, mime_content_type($file)),
   'colours[]' => ['red', 'yellow', 'blue'],
];


// NEEDED TO REMOVE THE NUMBERS BETWEEN SQUARE BRACKETS
$postFieldString = preg_replace('/%5B[0-9]+%5D/simU', '', http_build_query($postFields));

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFieldString);
$response = curl_exec($ch);
Robin Fuller
  • 153
  • 2
  • 9