How to upload files (multipart / form-data) using multidimensional POSTFIELDS using PHP and CURL?

I'm having trouble sending a multidimensional array with file uploads using PHP and CURL.

A multidimensional array, for example:

$post['question'] = 'Are you human?'; $post['answers'] = array('yes', 'no', 'maybe'); $post['file'] = '@/path/to/file'; // Output: Array( 'question' => Are you human?, 'answers' => Array( '0' => yes, '1' => no, '2' => maybe ), 'file' => @/path/to/file ) 

There are several reasons why this will not work if you simply try to publish this using CURLOPT_POSTFIELDS in CURL as follows:

 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://example.com'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); $response = curl_exec($ch); 

First of all, the official PHP description of CURLOPT_POSTFIELDS says:

Full details for publishing to HTTP "POST" operation. To publish the file, add filename with @ and use the full path. This can be passed as urlencoded string like 'para1 = val1 & para2 = val2 & ...' or as an array with the field name as the key and field data as the value. If the value is an array, the Content-Type header will set to multipart / form-data.

It looks like you can pass any type of POSTFIELDS array correctly? Wrong. POSTFIELDS accepts only non-scalar values ​​and suppresses the Array to string conversion error when transmitting multidimensional arrays. So the only other option you have is http_build_query() your array in order to be able to pass multidimensional arrays that don't choke.

But .. as you can read in the note on the PHP page:

Note. Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart / form-data, while passing a URL encoded string will encode the data as using / x-www-form-urlencoded.

The message will not be encoded in multipart / form-data if you pass the urlencoded line to POSTFIELDS, which will cause the file to fail to load.

Thus, it seems almost impossible to combine the two with CURL, while that would not be a problem if you were to use a regular HTML form.

My question is: can I get around this weird CURL quirk to be able to send multidimensional arrays and upload files?

+6
post php curl multidimensional-array file-upload
source share
3 answers

multipart / form-data does not support nested values. And I do not believe that CURL can do this either.

I suspect that the receiving end of your request is also a PHP script. If, then you can represent the nested array as one of the values, if you just prepared it yourself:

  $post['answers[0]'] = "yes"; $post['answers[1]'] = "no"; $post['answers[2]'] = "maybe"; 

Theoretically, you just need an 'answers[]' without an index, but this will overwrite the previous value and therefore will only work with http_build_query.

I am not sure if there is any HTTP library in PHP that can do this automatically.

+6
source share

Another way to execute the first answer:

 foreach( array("yes","no","maybe") as $key=>$value ) $post["answers[$key]"] = $value; 
+2
source share

Try this recursive function.

https://gist.github.com/yisraeldov/ec29d520062575c204be7ab71d3ecd2f

 <?php function build_post_fields( $data,$existingKeys='',&$returnArray=[]){ if(($data instanceof CURLFile) or !(is_array($data) or is_object($data))){ $returnArray[$existingKeys]=$data; return $returnArray; } else{ foreach ($data as $key => $item) { build_post_fields($item,$existingKeys?$existingKeys."[$key]":$key,$returnArray); } return $returnArray; } } 

And you can use it like this.

 curl_setopt($ch, CURLOPT_POSTFIELDS, build_post_fields($postfields)); 
+1
source share

All Articles