微信開發之上傳素材


本文目錄

  1. 上傳圖文素材的圖片
  2. 上傳其他素材
  3. 關鍵的http表單請求代碼
  4. 小結
  5. 參考文檔

**前言**: 我在實現微信公眾平台上傳素材的時候遇到了許多問題,但最終還是成功實現這一功能,特此在這里做一下總結和記錄。


文中遇到諸如 getAccessToken() 等關鍵函數卻沒有找到實現時,可參考前面的這兩篇文章:

1、微信開發之獲取用戶詳細列表
2、微信開發之向用戶群發文本消息


1、 **上傳圖文素材的圖片**

首先選一個簡單的接口來做說明例子,這個上傳素材的接口在所有上傳素材的接口中是參數最簡單的,而且還單獨享用一個URL, 作為入門例子再合適不過了。

注意,本文主要側重點是代碼層面的實現,而不是微信官方一大堆規則的講解,如果你有需要此方面的介紹,下面已給出官方鏈接不謝。

官方文檔:

新增永久素材

官方給的這個接口,除了需要慣例的 access_token ,還需要一個文件的參數,一般而言,只需要一個文件路徑,其他文件參數通過這個路徑獲取解析則可,做成一個黑匣子,簡單易用。
我知道,有人就是專門找下邊的 Requests::request() 的實現的,可在這就沒看到實現,別急,下面就有。

public function uploadNewsImage($path)
{
    $access_token = $this->getAccessToken();
    if (!$access_token) {
        return false;
    }

    $path = realpath($path);
    $post = ['media '=> '@'.$path];
    $url ="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={$access_token}";
    $return = $this->requestAndCheck($url, 'POST', $post);
    if ($return === false) {
        return false;
    }

    return $return;
}

/**
 * 專門用來檢查微信接口返回值的。
 * 是的,這個接口比上一兩篇文章的接口更加好用。東西一般做多,就知道要抽象了,如果還沒有那水平的話。
 */
public function requestAndCheck($url, $method = 'GET', $fields = [])
{
    $return = Requests::request($url, $method, $fields);
    if ($return === false) {
        $this->setError("request出錯! " . Requests::$error);
        return false;
    }

    $wxdata = json_decode($return, true);
    if (isset($wxdata['errcode']) && $wxdata['errcode'] != 0) {
        $this->setError("微信錯誤代碼:{$wxdata['errcode']};<br>錯誤信息:{$wxdata['errmsg']}<br>請求鏈接:$url");
        return false;
    }

    if (strtoupper($method) === 'GET' && empty($wxdata)) {
        $this->setError("微信http請求返回為空!<br>請求鏈接:$url");
        return false;
    }

    return $wxdata;
}

2、 **上傳其他素材**

懂得上面的流程,其他的上傳素材的接口,無非就是加多個 GETPOST 參數,主流程沒變。
其他相關接口列舉如下:

1、新增永久圖文素材:https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN
2、新增其他類型永久素材:https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE
3、新增臨時素材:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE


功能的約束和細節還望參考官方文檔:

1、新增永久素材
2、新增臨時素材


3、 **關鍵的http表單請求代碼**

先上代碼:(這里邊已經簡化很多附加功能,比如可以改變header之類的功能,該代碼主要參考一些開源的項目)

public static function request($url, $method = 'GET', $fields = [])
{
    self::$ch = curl_init();
    curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt(self::$ch, CURLOPT_CONNECTTIMEOUT, 10);

    $method = strtoupper($method);
    if ($method == 'GET' && !empty($fields)) {
        $url = $url . (strpos($url,"?")===false ? "?" : "&") . http_build_query($fields);
    }
    curl_setopt(self::$ch, CURLOPT_URL, $url);

    if ($method != 'GET') {
        curl_setopt(self::$ch, CURLOPT_POST, true);

        if (!empty($fields)) {
            if (is_array($fields)) {
                /* 支持文件上傳 */
                if (class_exists('\CURLFile')) {
                    curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, true);
                    foreach ($fields as $key => $value) {
                        if (is_string($value) && strpos($value, '@') === 0) {
                            $fields[$key] = new CURLFile(realpath(ltrim($value, '@')),
                            				'image/jpg', basename(ltrim($value, '@')));
                        }
                    }
                } elseif (defined('CURLOPT_SAFE_UPLOAD')) {
                    curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, false);
                }
            }
            curl_setopt(self::$ch, CURLOPT_POSTFIELDS, $fields);
        }
    }

    /* 關閉https驗證 */
    if ("https" == substr($url, 0, 5)) {
        curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt(self::$ch, CURLOPT_SSL_VERIFYHOST, false);
    }

    self::$content = curl_exec(self::$ch);
    curl_close(self::$ch);

    return self::$content;
}


重點分析:

/* 支持文件上傳 */
if (class_exists('\CURLFile')) {
    curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, true);
    foreach ($fields as $key => $value) {
        if (is_string($value) && strpos($value, '@') === 0) {
            $fields[$key] = new CURLFile(realpath(ltrim($value, '@')));
        }
    }
} elseif (defined('CURLOPT_SAFE_UPLOAD')) {
    curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, false);
}

這里面有個php版本的坑,5.4版本只支持用 @ 來進行上傳文件,5.5是個過渡版本,支持 @CURLFile 兩種方式上傳文件,而到了5.6,就只支持 CURLFile 了。所以需要用兼容模式來適應不同版本。

關於為什么不用php版本號來判斷呢?你用版本號誰知道你是要來判斷啥呢?難道加個注釋?
而常量 CURLOPT_SAFE_UPLOAD 是用來開啟是否支持 @ 的,當然,5.6版本設置了也沒有。

還有,要上傳file的時候,一定要用數組給 curl_setopt(self::$ch, CURLOPT_POSTFIELDS, $fields); 傳值,而不能用 http_build_query() ,一個的http請求頭中的 content-typemultipart/form-date ,另一個是 application/x-www-form-urlencoded 。file用二進制編碼進行傳輸,而普通的post數據是文本傳輸。

上面的相關知識還請詳看 參考文檔


**小結**: 如果你已有上傳文件的接口,其實這個功能不算啥,按照官方文檔進行 post url 即可。如果沒有,或者沒有實現文件上傳功能,就要對 curl 研究一下了,還要踩一下php版本的坑。。。不過對 curl 掌握就更加全面而牢固了,這難道不是我們的目的?
*主要參考文檔*: > 1、[微信公眾號開發文檔](https://mp.weixin.qq.com/wiki) > 2、[Multipart/form-data POST文件上傳詳解](http://blog.csdn.net/xiaojianpitt/article/details/6856536) > 3、[PHP的CURLOPT_POSTFIELDS參數使用數組和字符串的區別](http://blog.csdn.net/fableboy/article/details/18973483) > 4、[The CURLFile class](http://php.net/manual/zh/class.curlfile.php) > 5、[考慮 PHP 5.0~5.6 各版本兼容性的 cURL 文件上傳](https://segmentfault.com/a/1190000000725185)


-end-


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM