I have an API I am trying to use that accepts multiple files in a single HTTP POST via multipart form data.
The problem is, the files have the same key (images
). In Postman, the sample request looks like so:
And in cURL this works too:
curl --location 'http://my-amazing-service.local'
--form 'images=@"/Users/zach/Desktop/1.jpg"'
--form 'images=@"/Users/zach/Desktop/2.jpg"'
--form 'images=@"/Users/zach/Desktop/3.jpg"'
The problem is in PHP, CURLOPT_POSTFIELDS
does not take multidimensional arrays. For whatever reason, it works on my Mac I do anyway, but not inside a Docker container running Alpine Linux.
When I run the code below on Alpine Linux (in a Docker container), I can see from the Content-Length
in the header is only 146
, meaning the binary contents of the image are not being included (my test image is about 50KB).
Is it possible to pass multiple files into CURLOPT_POSTFIELDS
? I’d rather not have to write the raw multipart POST body manually if possible.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'http://my-amazing-service.local',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 0,
CURLOPT_POSTFIELDS => [
'images' => [
file_get_contents('1.jpg'),
file_get_contents('2.jpg'),
file_get_contents('3.jpg'),
],
]
));
$verbose = fopen('php://temp', 'w+');
curl_setopt($curl, CURLOPT_STDERR, $verbose);
curl_setopt($curl, CURLOPT_VERBOSE, true);
$response = curl_exec($curl);
if ($response === FALSE) {
printf("cURL error: %sn", curl_error($curl));
}
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
echo "Verbose information:n<pre>", $verboseLog, "</pre>n";
curl_close($curl);
2
Answers
After some more checking, it looks like the reason it's so hard to send a bunch of files in the same field name is because it technically violates RFC 2388:
So this problem just went from a "Can I do it?" to a "Should I do it?"
I think the better solution is to reach out to the API maintainer and bring this up.
You can use the function
curl_file_create
to attach multiple files on your request, e.g:Using your approach:
In order to use a single
key
on theCURLOPT_POSTFIELDS
, you have to use the same syntax used to pass an array in a query string:This is the same syntax that we use to pass an array of values on a query string: