博客 / 詳情

返回

利用微信公眾號提供的官方API上傳圖片獲取永久圖片素材!當圖牀用!

需求

自己開發的小程序,例如社區類、電商類、新聞、博客等類型小程序,會需要儲存很多圖片,圖片資源會給個人開發者帶來很多成本,萬一訪問量大了,網站帶寬、流量也會不堪重負,所以圖片資源必然不合適儲存在自己的服務器裏面,而很多廠商提供的彈性儲存也是按需付費的。

想法

微信公眾平台提供了一個素材管理,裏面可以上傳圖片、視頻、音頻等類型的素材,那麼是否可以將圖片素材上傳上去,獲取到url作為自己小程序項目的圖片服務器呢?當然沒問題!

根據開發文檔的説法:永久圖片素材新增後,將帶有URL返回給開發者,開發者可以在騰訊系域名內使用(騰訊系域名外使用,圖片將被屏蔽)。簡單來説就是你只能在騰訊的平台使用這個圖片素材URL,否則無法展示,因為有防盜鏈。

開發

根據微信公眾平台開發文檔提供的【新增永久素材】接口可知,分為以下幾個步驟實現上傳圖片素材到微信服務器。

  1. 獲取access_token
  2. 調用新增永久素材接口進行上傳素材
  3. 獲取到素材的永久URL

代碼如下:

<?php

// 返回JSON
header("Content-type:application/json");
// 允許上傳的圖片後綴
$allowedExts = array("jpeg", "jpg", "png");
// 後綴名
if ($allowedExts[0] == 'jpeg') {
    $hzm = 'jpg';
}else{
    $hzm = $allowedExts[0];
}
// 獲取選擇的文件
$temp = explode(".", $_FILES["file"]["name"]);
// 獲取文件後綴名
$extension = end($temp);

if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 10485760)
&& in_array($extension, $allowedExts)){
    if ($_FILES["file"]["error"] > 0){
        $result = array(
            'code' => 201,
            'msg' => '上傳失敗'.$_FILES["file"]["error"]
        );
    }else{
        // 重命名
           $new_file = date("Y-m-d")."-".rand(10000,99999).".".$hzm;
           // 上傳到自己的服務器
        move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$new_file);
        // 獲取真實地址
        $filepath = realpath(dirname(__FILE__));
        $upload_filepath = $filepath."/upload/".$new_file;
        // 上傳到微信服務器
        $imgurl = upload_img($upload_filepath);
        // 驗證上傳結果
        if(strpos($imgurl,'http') !== false){

            // 上傳成功
            $result = array(
                'code' => 200,
                'msg' => '上傳成功',
                'url' => $imgurl
            );
            // 刪除本地素材
            unlink($upload_filepath);
        }else{

            // 上傳失敗
            $result = array(
                'code' => 202,
                'msg' => '上傳失敗'
            );
        }
    }
}

// 獲取access_token
function getToken(){
    // appid和secret
    $appid='填寫你公眾號的appid';
    $appsecret='填寫你公眾號的appsecret';
    // 讀取access_token
    include './access_token.php';
    // 判斷是否過期
    if (time() > $access_token['expires']){
        // 如果已經過期就得重新獲取並緩存
        $access_token = array();
        $access_token['access_token'] = getNewToken($appid,$appsecret);
        $access_token['expires']=time()+7000;
        // 將數組寫入php文件
        $arr = '<?php'.PHP_EOL.'$access_token = '.var_export($access_token,true).';'.PHP_EOL.'?>';
        $arrfile = fopen("./access_token.php","w");
        fwrite($arrfile,$arr);
        fclose($arrfile);
        // 返回當前的access_token
        return $access_token['access_token'];
    }else{
        // 如果沒有過期就直接讀取緩存文件
        return $access_token['access_token'];
    }
}
// 獲取新的access_token
function getNewToken($appid,$appsecret){
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
    $access_token_Arr =  https_request($url);
    return $access_token_Arr['access_token'];
}
// curl請求函數
function https_request ($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $out = curl_exec($ch);
    curl_close($ch);
    return  json_decode($out,true);
}
// 上傳圖片素材到微信服務器
function upload_img($realpath){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.getToken().'&type=image');
    $data = array(
        'media' => new CURLFile($realpath)
    );
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $upimg = curl_exec($ch);
    return json_decode($upimg)->url;
    curl_close($ch);
}

// 返回JSON對象
echo json_encode($result,JSON_UNESCAPED_UNICODE);
?>

請求返回

{"media_id":"8IZhZUPXxsG_omeA5giO5By8VyHnjk7_oy0Co9jVWwxpgm-sqhx_Hkz_9rLVF9Ws","url":"http:\/\/mmbiz.qpic.cn\/mmbiz_png\/5zLSKyuEW2Kt5ZGZg7XUx05QyGOVFCpHqKic74qQP4gxzQJYXjwN4aGEiadtfUXax4fCXXV5ia1UnvSwdqxuqLCqA\/0?wx_fmt=png","item":[]}

代碼解釋

  1. 首先要將圖片從客户端(小程序端)上傳到你自己的服務器的upload目錄
  2. 然後調用新增永久素材接口從upload目錄上傳到微信的服務器
  3. 需要配置公眾號的appid和appsecret獲取access_token
  4. 新增永久素材接口需要傳入access_token才可以調用
  5. access_token有效期是2小時,每天最多獲取2000次access_token,超過次數就獲取不到,為了能夠保證一直都能獲取到新的token,不能每上傳一次就獲取一個新的access_token,量大的話一下子就把2000次用完了。access_token只要在2小時內都可以隨便使用,所以需要進行緩存access_token。getToken()這個函數就是緩存access_token的步驟(如果access_token已經超過2小時就獲取新的access_token並緩存到本地,如果access_token還沒超過2小時直接讀取本地緩存的access_token)
  6. 獲取access_token接口需要在公眾號後台的安全中心配置白名單ip地址

注意

圖片鏈接只能在騰訊域名的平台使用,在自建網站無法顯示,本文主要將的是小程序調用永久圖片素材,是可以用的!

小妙招

如果需要在非騰訊域名下使用永久圖片素材的URL,需要搭配反防盜鏈圖片跳板,類似http://xxx.com/?imgurl=永久圖片素材URL來繞過防盜鏈,簡單來説就是一個圖片服務器代理吧。

作者

TANKING

user avatar xiaoweiyu 頭像 ailim 頭像 sunshine_591c4563d4a83 頭像 nidexiaoxiongruantangna 頭像 maogexiaodi 頭像 huangjuyuan 頭像 zeran 頭像
7 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.