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

curl options php
php curl multipart upload
how to use curl in php
how to fetch data using curl in php
curl php post upload file
curl upload file in php
create curl file php
curl post file upload

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!

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.

Mixing multiple values ​​for the same key and uploading files using , Mixing multiple values ​​for the same key and uploading files using cURL and PHP Ive encountered a limitation in cURL bindings for PHP. There seems Here's how to upload/transfer a file server-to-server using PHP cURL (this is not a 'client' web form upload). The receiving server requires the top level key in the post data array to be 'file'. See the comments in the code.

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

Using cURL in PHP, 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  This is how to upload two or more files at once with cURLFile. With modern browser support, you can upload many files at one time if the multiple attribute is given.

I ran into the same issue. But I was able to solve it this way.

for($cnt = 0; $cnt < count($siteRows); $cnt++)
{
    $curlParams['site_ids['.$cnt.']'] = $siteRows[$cnt]->site_id; 
}

Works for files too:

for($cnt = 0; $cnt < count($imageRows); $cnt++)
{
    $curlParams['product_images['.$cnt.']'] = '@'.$imageRows[$cnt]->full_path;
}

CURLFile - Manual, value, The value to be set on the cURL handle for the given option the resource $curl = curl_init(); // set the URL and other options curl_setopt($curl, CURLOPT_URL, Sending multi-dimensional data and multiple files with CurlFile in one request We save each object in the $files array with keys named "upload[0]" and  Uploading multiple files. Multiple files can be uploaded using different name for input. It is also possible to upload multiple files simultaneously and have the information organized automatically in arrays for you.

I got it working using:

curl_setopt($ch, CURLOPT_POSTFIELDS,array('tag[0]'=>'val0','tag[1]'=>'val1'));

then $_POST results in: $_POST['tag'][0] = 'val0' and $_POST['tag'][1] = 'val1'

curl_setopt - Manual, CURLFile should be used to upload a file with CURLOPT_POSTFIELDS . public mixed $ postname ; The name of the file in the upload data (defaults to the name property). With modern browser support, you can upload many files at one time if the multiple attribute is Convert values for keys starting with '@' prefix You can use the Condition element of a policy to test multiple keys or multiple values for a single key in a request. When you make a request to AWS, either programmatically or through the AWS Management Console, your request includes information about your principal, operation, tags, and more.

I think the established standard for multiple values in one key (or the same key) is to have it concatenated with a delimiter, such as for multiple selections of option lists in form elements. I believe this delimiter is the tab character (\t) or the pipe symbol (|).

If the keyname is terminated with [] (like tag[]), PHP will automatically convert the values into an array for your convenience.

curl_setopt_array - Manual, curl_setopt ( resource $ch , int $option , mixed $value ) : bool This value can be retrieved using the CURLINFO_FILETIME option with curl_getinfo(). CURLFile may be used for uploads instead. From curl 7.66.0 onwards 1 and 2 is treated as the same value. The string can be the file name of your pinned public key. If you set every curl handle to update a shared cookiejar on close you may overwrite the new found session value with the old session value depending on the closing order of your handles. Also, because the cookiejar is only written to on a curl_close, you may be using dissimilar or old session info in some of your 'faked browser tabs'.

cURL - Manual, curl_setopt_array — Set multiple options for a cURL transfer An array specifying which options to set and their values. The keys should be valid curl_setopt() constants or their integer equivalents. set URL and other appropriate options As with curl_setopt(), passing an array to CURLOPT_POST will encode the data as  Clarification on the MAX_FILE_SIZE hidden form field: PHP has the somewhat strange feature of checking multiple "maximum file sizes". The two widely known limits are the php.ini settings "post_max_size" and "upload_max_size", which in combination impose a hard limit on the maximum amount of data that can be received.

I can't see any other issues with this function however. In order to use curl with secure sites you will need a ca-bundle.crt file; here's a PHP script I've written  You can use curl_multi_getcontent() on a curl handle that was executed with curl_exec() (and not added to a multi handle). However, this is not very useful because curl_multi_getcontent() will return the same as curl_exec() then.

The PHP CURL extension allows retrieving data from Web servers of multiple URLs at the same time, however this may overload the server of a given site. This class provides a solution that makes this task lighter by just sending the request to the first URL of a list and only after that it sends the requests to the remaining URLs of that list.

Comments
  • I believe this answers my question, but I see now way to actually "answer" my question. :) Please upvote this so maybe someday someone can accept it for me or something?
  • you can, as of now, accept your own answers, see blog.stackoverflow.com/2009/01/accept-your-own-answers
  • Surprised nobody else has ever come across this, seems like something that should be part of the cURL php library! Thanks for making my life easier!
  • i have been stuck in this hell hole for 3 days at first i didn't event know what i was doing wrong i only understood after making a form and checking the request from dev tools its 2018 and this still has no proper solution wth besides @BeauSimensen your blog is down man
  • Website is down, you can see function here yeehuichan.wordpress.com/2011/08/07/…
  • I know how to create arrays in forms and URLs for PHP to read. The problem is that I'm posting to a non-PHP site that does not use the [] hack. Even if it did, cURL will not accept 'tag[]' => array('a', 'b', 'c') and create the request like you are suggesting it will. This is the problem.
  • Takes advantage of php's specific interpretation of post field names, so works only if your target is running php, but being as this is a question about writing the client side in php I suppose that's likely. It helped me, +1
  • I know how to get PHP to accept an array with tag[], but that is not the problem. I am posting to a non-PHP site using cURL and need to be able to send multiple values for the same key (tag), and I could not get cURL to do that, whether I specify 'tag' or 'tag[]' as the param name.
  • Mhmm, not sure I get this right. You're posting to so-to-say somebody elses form (which is perfectly fine) ? Doesn't the original html-form allow for multiple entries in that form-element ? If no, the receiving code will not expecting it. If yes, get wireshark and look how it is encoded, then replay
  • I know they accept multiple values for the same tag ( tag=a&tag=b ) and they do not use the tag[]=a&tag[]=b format. I built a Google Code automatic uploader, and I believe that site is in Python. I had to build a custom postfields to build a multipart/form-data postinfo.
  • Also, my description on th esolution is at the bottom of the list. I wish I could accept my own answer! Or at least get some +1's on it so that it gets moved to the top. Thanks again for your help, lImbus.
  • See @BeauSimensen's answer below.