PHP 和 cURL - 包含文件和文本的多格式请求
PHP and cURL - Multiform request with file and text
我需要发送一个包含要上传的文件以及 JSON 字符串的 cURL 请求。发送 JSON 时我可以获得格式正确的请求,但文件将其丢弃。
$postData = array(
'JSON'=> json_encode($jsonParams),
$reference => '@'.$tmp_file_path
);
//Borrowed function from: http://scraperblog.blogspot.com/2013/07/php-curl-multipart-form-posting.html
function multipart_build($fields, $boundary){
$retval = '';
foreach($fields as $key => $value){
$retval .= "--$boundary\nContent-Disposition: form-data; name=\"$key\"\n\n$value\n";
}
$retval .= "--$boundary--";
return $retval;
}
$boundary = "--requestboundary-xxx";
$request = $this->multipart_build($postData,$boundary);
$curl = curl_init();
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: multipart/form-data; boundary=$boundary"));
curl_setopt($curl, CURLOPT_URL, $target);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
$reference 需要绑定到 $jsonParams 中的值,以便接收服务器可以确保上传的文件附加到相应的数据字符串包。
////////////////////////////////////////// //////////////
在 Marc B 发表评论后更新
////////////////////////////////////////// //////////////
所以我的第一个方法不是使用我自己的多部分。我选择 multipart 的原因至少是我从服务器得到了响应。这是原代码。
$curl_file_object = curl_file_create($attachmentFile['tmp_name'], $attachmentFile['type'], $reference);
$postData= array(
'JSON'=> json_encode($jsonParams),
$reference => $curl_file_object,
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $target);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: multipart/form-data;"));
curl_setopt($curl, CURLOPT_POST, true); // enable posting
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); // post data
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // if any redirection after upload
$response = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
debug($info);
然后我得到:
[url] => --------
[content_type] =>
[http_code] => 0
[header_size] => 0
[request_size] => 0
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.031
[namelookup_time] => 0
[connect_time] => 0.031
[pretransfer_time] => 0
[size_upload] => 0
[size_download] => 0
[speed_download] => 0
[speed_upload] => 0
[download_content_length] => -1
[upload_content_length] => -1
[starttransfer_time] => 0
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => --------
[certinfo] => Array
(
)
[primary_port] => --------
[local_ip] => --------
[local_port] => --------
有了 multipart,我至少得到了 400。
不要构建自己的多部分。 Curl 完全有能力为您做到这一点:
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
它会获取一个数组并自动执行任何需要的操作。
如果您使用的是 PHP 5.5+,您也可以将 curlfile 用于文件部分,而无需 @
hack。
使用 CURLFile 而不是 curl_file_create() 解决了这个问题。即使它们应该是相同的...
我需要发送一个包含要上传的文件以及 JSON 字符串的 cURL 请求。发送 JSON 时我可以获得格式正确的请求,但文件将其丢弃。
$postData = array(
'JSON'=> json_encode($jsonParams),
$reference => '@'.$tmp_file_path
);
//Borrowed function from: http://scraperblog.blogspot.com/2013/07/php-curl-multipart-form-posting.html
function multipart_build($fields, $boundary){
$retval = '';
foreach($fields as $key => $value){
$retval .= "--$boundary\nContent-Disposition: form-data; name=\"$key\"\n\n$value\n";
}
$retval .= "--$boundary--";
return $retval;
}
$boundary = "--requestboundary-xxx";
$request = $this->multipart_build($postData,$boundary);
$curl = curl_init();
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: multipart/form-data; boundary=$boundary"));
curl_setopt($curl, CURLOPT_URL, $target);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
$reference 需要绑定到 $jsonParams 中的值,以便接收服务器可以确保上传的文件附加到相应的数据字符串包。
////////////////////////////////////////// //////////////
在 Marc B 发表评论后更新
////////////////////////////////////////// //////////////
所以我的第一个方法不是使用我自己的多部分。我选择 multipart 的原因至少是我从服务器得到了响应。这是原代码。
$curl_file_object = curl_file_create($attachmentFile['tmp_name'], $attachmentFile['type'], $reference);
$postData= array(
'JSON'=> json_encode($jsonParams),
$reference => $curl_file_object,
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $target);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: multipart/form-data;"));
curl_setopt($curl, CURLOPT_POST, true); // enable posting
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); // post data
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // if any redirection after upload
$response = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
debug($info);
然后我得到:
[url] => --------
[content_type] =>
[http_code] => 0
[header_size] => 0
[request_size] => 0
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.031
[namelookup_time] => 0
[connect_time] => 0.031
[pretransfer_time] => 0
[size_upload] => 0
[size_download] => 0
[speed_download] => 0
[speed_upload] => 0
[download_content_length] => -1
[upload_content_length] => -1
[starttransfer_time] => 0
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => --------
[certinfo] => Array
(
)
[primary_port] => --------
[local_ip] => --------
[local_port] => --------
有了 multipart,我至少得到了 400。
不要构建自己的多部分。 Curl 完全有能力为您做到这一点:
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
它会获取一个数组并自动执行任何需要的操作。
如果您使用的是 PHP 5.5+,您也可以将 curlfile 用于文件部分,而无需 @
hack。
使用 CURLFile 而不是 curl_file_create() 解决了这个问题。即使它们应该是相同的...