Php Curl send File AND array data
After very long research to manage the same problem, I think that a simpler solution could be:
$postValues = Array("test[0]" => 1, "test[1]" => 2, "test[2]" => 3);
this is the right way to emulate what happen on browsers
<input type="hidden" name="test[0]" value="1"><input type="hidden" name="test[1]" value="2">...
The result is:
Array( [test] => Array ( [0] => 1 [1] => 2 [2] => 3 ))Array( [file] => Array ( [name] => upload.txt [type] => application/octet-stream [tmp_name] => /tmp/phprRGsPU [error] => 0 [size] => 30 ))
After long research and testing i`ve got the (not very nice but working) solution:
function createHttpHeader($postValues, $overrideKey = null) { global $delimiter; // invalid characters for "name" and "filename" $disallow = array("\0", "\"", "\r", "\n"); $data = Array(); if (!is_array($postValues)) { $postValues = Array($postValues); } foreach($postValues as $key => $value) { $useKey = $overrideKey === null ? $key : $overrideKey. "[$key]"; $useKey = str_replace($disallow, "_", $useKey); if (is_array($value)) { $data = array_merge($data, addPostData($value, $useKey)); } else { $data[] = "--". $delimiter. "\r\n"; $data[] = "Content-Disposition: form-data; name=\"". $useKey. "\""; if (is_a($value, "\CurlFile")) { $data[] = "; filename=\"". basename($value->name). "\"\r\n"; $data[] = "Content-Type: application/octet-stream\r\n\r\n"; $data[] = file_get_contents($value->name). "\r\n"; } else { $data[] = "\r\n\r\n". $value. "\r\n"; } } } return $data;}
Test with:
$postValues = Array( "blaat" => 1, "test" => Array(1,2,3), "grid" => Array(0 => array(1,2), 1 => array(4,5)), "gridComplex" => Array("rows" => array(1,2), "columns" => array(0 => array(1,2,3,4), 1 => array(4,5,4,5))) );$postValues["file[0]"] = new CurlFile($file, "text/plain");$postValues["file[1]"] = new CurlFile($file, "text/plain");// print_r(new CurlFile($file));exit;$delimiter = "-------------" . uniqid();$data = createHttpHeader($postValues);$data[] = "--" . $delimiter . "--\r\n";$data = implode("", $data);$curl = curl_init();curl_setopt($curl, CURLOPT_URL, "localhost/curl/post.php");curl_setopt($curl, CURLOPT_HTTPHEADER , array('Content-Type: multipart/form-data; boundary=' . $delimiter, 'Content-Length: ' . strlen($data)));curl_setopt($curl, CURLOPT_POST, true);curl_setopt($curl, CURLOPT_POSTFIELDS, $data);curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);$curlResult = curl_exec($curl);echo $curlResult;
Edit: addition the addPostData function:
function addPostData($postValues, $delimiter, $overrideKey = null) { // invalid characters for "name" and "filename" $disallow = array("\0", "\"", "\r", "\n"); $data = Array(); if (!is_array($postValues)) { $postValues = Array($postValues); } foreach($postValues as $key => $value) { $useKey = $overrideKey === null ? $key : $overrideKey. "[$key]"; $useKey = str_replace($disallow, "_", $useKey); if (is_array($value)) { $data = array_merge($data, $this->addPostData($value, $delimiter, $useKey)); } else { $data[] = "--". $delimiter. "\r\n"; $data[] = "Content-Disposition: form-data; name=\"". $useKey. "\""; if (is_a($value, "\CurlFile")) { $data[] = "; filename=\"". basename($value->postname). "\"\r\n"; $data[] = "Content-Type: ". $value->mime. "\r\n\r\n"; $data[] = file_get_contents($value->name). "\r\n"; } else { $data[] = "\r\n\r\n". $value. "\r\n"; } } } return $data; }