Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing multiple values for the same key and file uploads using cURL and PHP

Tags:

php

curl

I’ve run into a limitation in the cURL bindings for PHP. It appears there is no easy way to send the same multiple values for the same key for postfields. Most of the workarounds I have come across for this have involved creating the URL encoded post fields by hand tag=foo&tag=bar&tag=baz) instead of using the associative array version of CURLOPT_POSTFIELDS.

It seems like a pretty common thing to need to support so I feel like I must have missed something. Is this really the only way to handle multiple values for the same key?

While this workaround might be considered workable (if not really annoying), my main problem is that I need to be able to do multiple values for the same key and also support file upload. As far as I can tell, file upload more or less requires to use the associate arravy version of CURLOPT_POSTFIELDS. So I feel like I am stuck.

I have posted about this problem in more detail on the cURL PHP mailing list in the hopes that someone there has some ideas about this.

Suggestions or hints on where I can look for more information on this are greatly appreciated!

like image 874
Beau Simensen Avatar asked Dec 31 '08 10:12

Beau Simensen


2 Answers

I ended up writing my own function to build a custom CURLOPT_POSTFIELDS string with multipart/form-data. What a pain.

function curl_setopt_custom_postfields($ch, $postfields, $headers = null) {
    // $postfields is an assoc array.
    // Creates a boundary.
    // Reads each postfields, detects which are @files, and which values are arrays
    // and dumps them into a new array (not an assoc array) so each key can exist
    // multiple times.
    // Sets content-length, content-type and sets CURLOPT_POSTFIELDS with the
    // generated body.
}

I was able to use this method like this:

curl_setopt_custom_postfields($ch, array(
    'file' => '@/path/to/file',
    'tag' => array('a', 'b', 'c'),
));

I am not certain of CURLOPT_HTTPHEADER stacks, so since this method calls it, I made certain that the function would allow for the user to specify additonal headers if needed.

I have the full code available in this blog post.

like image 68
Beau Simensen Avatar answered Sep 20 '22 17:09

Beau Simensen


If you use tag[] rather than tag for the name, PHP will generate an array for you, in other words, rather than

tag=foo&tag=bar&tag=baz

You need

tag[]=foo&tag[]=bar&tag[]=baz

Note that when urlencoded for transmission this should become

tag%5B%5D=foo&tag%5B%5D=bar&tag%5B%5D=baz
like image 44
Paul Dixon Avatar answered Sep 18 '22 17:09

Paul Dixon