1. 程式人生 > >PHP5.6之後curl上傳圖片

PHP5.6之後curl上傳圖片

PHP5.6 之後curl上傳圖片

問題描述

在開發微信公眾號的過程中,需要上傳臨時資源圖片,根據微信開發文件,採用curl進行後臺的表單提交:

微信官方文件介面呼叫請求說明
http請求方式: POST/FORM
http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
呼叫示例(使用curl命令,用FORM表單方式上傳一個多媒體檔案):
curl -F 
[email protected]
.jpg "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"

根據上述文件,curl 上傳圖片的程式碼片段如下,這段程式碼在PHP5.5上正常執行:

$url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={$access_token}&type={$type}";
$data = array('media' => '@' . $img
); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch
, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $info = curl_exec($ch); curl_close($ch); return $info;

最近升級到PHP7之後,出現上傳圖片失敗:

{"errcode":41005,"errmsg":"media data missing hint: [lFlbea0043e621]"}

問題根源[email protected]字首使用

檢視PHP官方手冊,關於curl post 檔案的傳輸CURLOPT_POSTFIELDS:

全部資料使用HTTP協議中的 "POST" 操作來發送。 要傳送檔案,在檔名前面加上@字首並使用完整路徑。 

檔案型別可在檔名後以 ';type=mimetype' 的格式指定。 這個引數可以是 urlencoded 後的字串,類似'para1=val1&para2=val2&...',也可以使用一個以欄位名為鍵值,欄位資料為值的陣列。

 如果value是一個數組,Content-Type頭將會被設定成multipart/form-data。 

從 PHP 5.2.0 開始,使用 @ 字首傳遞檔案時,value 必須是個陣列。 從 PHP 5.5.0 開始, @ 字首已被廢棄,檔案可通過 CURLFile 傳送。 

設定 CURLOPT_SAFE_UPLOAD 為 TRUE 可禁用 @ 字首傳送檔案,以增加安全性。

再檢視CURLOPT_SAFE_UPLOAD相關說明:

PHP 5.5.0 中新增,預設值 FALSE。 PHP 5.6.0 改預設值為 TRUE

所以很清楚可以看到,我們的問題是上級到PHP7之後,預設的CURLOPT_SAFE_UPLOAD為TRUE,禁止@ 字首傳送檔案;而且解決辦法有兩個:

  1. 設定CURLOPT_SAFE_UPLOAD為false;
  2. 採用CURLFile 安全上傳檔案;

採用CURLFile 安全上傳檔案

$url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={$access_token}&type={$type}";
//構建CURLFile檔案
$cfile = new CURLFile("$img",'image/jpg');
$imgdata = array('media' => $cfile);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $imgdata );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$info = curl_exec($ch);
curl_close($ch);
return $info;