小程式開發:上傳圖片到騰訊雲

goodspeed發表於2017-08-27

這是小程式開發第二篇,主要介紹如何上傳圖片到騰訊雲,之所以選擇騰訊雲,是因為騰訊雲免費空間大?

準備工作

上傳圖片主要是將圖片上傳到騰訊雲物件儲存(COS)。

要使用物件儲存 API,需要先執行以下步驟:

  1. 購買騰訊雲物件儲存(COS)服務
  2. 在騰訊雲 物件儲存控制檯 裡建立一個 Bucket
  3. 在控制檯 個人 API 金鑰 頁面裡獲取 AppID、SecretID、SecretKey 內容
  4. 編寫一個請求籤名演算法程式(或使用任何一種服務端 SDK)
  5. 計算簽名,呼叫 API 執行操作

所以我們要做的準備工作有:

image
image

這些配置過程這裡就不做說明了,接下來主要介紹步驟4、5。

小程式上傳圖片到 cos 流程如下圖:

圖片上傳流程圖
圖片上傳流程圖

在這個過程中我們需要實現的是,鑑權伺服器返回簽名的步驟以及小程式的相關步驟。

COS鑑權服務

使用物件儲存服務 COS 時,可通過 RESTful API 對 COS 發起 HTTP 匿名請求或 HTTP 簽名請求,對於簽名請求,COS 伺服器端將會進行對請求發起者的身份驗證。

  • 匿名請求:HTTP 請求不攜帶任何身份標識和鑑權資訊,通過 RESTful API 進行 HTTP 請求操作。
  • 簽名請求:HTTP 請求時新增簽名,COS伺服器端收到訊息後,進行身份驗證,驗證成功則可接受並執行請求,否則將會返回錯誤資訊並丟棄此請求。
    騰訊雲COS物件儲存,基於金鑰 HMAC (Hash Message Authentication Code) 的自定義 HTTP 方案進行身份驗證。

上傳圖片是一個簽名請求,需要進行簽名驗證。之所以我們

簽名流程

客戶通過對 HTTP 請求進行簽名,並將簽名後的請求傳送至騰訊雲進行簽名驗證,具體流程如下圖所示。

簽名流程
簽名流程

我們使用 sdk 開發,這個流程大致瞭解下就行,簽名的實現 sdk 已經包含,只需要呼叫方法即可。

通過簽名流程我們可以知道,簽名需要 SecretId 和 SecretKey,這兩個資訊不適合存放在客戶端中,這也是我們單獨部署一個鑑權伺服器的主要原因。

簽名生成 API

上一篇小程式開發:python sanic 實現小程式登入註冊 我們介紹過,服務端使用 sanic 框架 + swagger_py_codegen 生成 rest-api。

新增簽名生成 api 我們需要先在文件中新增 API 的相關描述。文件程式碼:https://github.com/gusibi/Metis/blob/master/docs/v1.yml

    /qc_cos/config:
        get:
            summary: 騰訊雲配置
            description: 騰訊雲配置
            tags: [Config]
            operationId: get_qc_cos_config
            parameters:
                - $ref: '#/parameters/AccessToken'
                - $ref: '#/parameters/qcos_path_in_query'
            responses:
                200:
                    schema:
                        $ref: '#/definitions/QCOSConfig'
                default:
                    description: Unexpected error
                    schema:
                        $ref: '#/definitions/Error'
            security:
                - OAuth2: [open]複製程式碼

這個介面我們要求登入才能呼叫。
文件定義完成之後,呼叫

swagger_py_codegen -s  docs/v1.yml . -p apis -tlp sanic複製程式碼

生成程式碼模板,API 程式碼實現如下:
```python
from qcloud_cos.cos_auth import Auth

async def get(self, request):
    auth = Auth(appid=Config.QCOS_APPID,
                secret_id=Config.QCOS_SECRET_ID,
                secret_key=Config.QCOS_SECRET_KEY)
    expired = time() + 3600 # 簽名有效時間 3600 秒
    # 上傳到 cos bucket 的目錄
    dir_name = request.raw_args.get('cos_path', '/xrzeti')
    # 生成簽名
    sign = auth.sign_more(Config.QCOS_BUCKET_NAME,
                          cos_path=dir_name,
                          expired=expired)
    return {"sign": sign}, 200複製程式碼

> 由於 騰訊雲COSv4 的Python SDK 只支援 python2,而 sanic 需要 python3.5+ 所以,這裡我 fork 出來一份新增了 python3 的支援。
[https://github.com/gusibi/cos-python-sdk-v4](https://github.com/gusibi/cos-python-sdk-v4)。使用 python3 環境的可以使用這個版本。

##  上傳圖片到 cos

### 選擇圖片

> `wx.chooseImage(OBJECT)`
從本地相簿選擇圖片或使用相機拍照。

呼叫這個方法,小程式會把選擇的圖片放到臨時路徑(在小程式本次啟動期間可以正常使用,如需持久儲存,需在主動呼叫 wx.saveFile,在小程式下次啟動時才能訪問得到),我們只能將臨時路徑的檔案上傳。

核心程式碼如下:

```js
    uploadToCos: function () {
        var that = this;

        // 選擇上傳的圖片
        wx.chooseImage({
            sizeType: ['original', 'compressed'], // 圖片型別 original 原圖,compressed 壓縮圖,預設二者都有
            success: function (res) {

                // 獲取檔案路徑
                var file = res.tempFiles[0];
                console.log(file.size);

                // 獲取檔名
                var fileName = file.path.match(/(wxfile:\/\/)(.+)/)
                fileName = fileName[2]

                // 獲取到圖片臨時路徑後,指定檔名 上傳到cos
                upload(file.path, fileName, that);
            }
        })
    }複製程式碼

這裡圖片選擇成功後,我們取原圖上傳到 cos。

上傳圖片

cos 上傳圖片的URL由 cos_region,appid,bucket_name和 cos_dir_name 拼接而成。
把以下欄位配置成自己的cos相關資訊,詳情可看API文件

cosUrl = "https://" + REGION + ".file.myqcloud.com/files/v2/" + APPID + "/" + BUCKET_NAME + DIR_NAME;複製程式碼

REGION: cos上傳的地區
APPID: 賬號的appid
BUCKET_NAME: cos bucket的名字
DIR_NAME: 上傳的檔案目錄

var config = require('../config.js');
// 先確定上傳的 URL
var cosUrl = "https://" + config.cos_region + ".file.myqcloud.com/files/v2/" + config.cos_appid + "/" + config.cos_bucket_name + config.cos_dir_name;

//填寫自己的鑑權伺服器地址
var cosSignatureUrl = config.host + '/v1/qc_cos/config?cos_path=' + config.cos_dir_name;

/**
 * 上傳方法
 * filePath: 上傳的檔案路徑
 * fileName: 上傳到cos後的檔名
 * that: 小程式所在當前頁面的 object
 */
function upload(filePath, fileName, that) {
    var data;

    // 鑑權獲取簽名
    wx.request({
        url: cosSignatureUrl,
        header: {
            Authorization: 'JWT' + ' ' + that.data.jwt.access_token
        },
        success: function (cosRes) {
            // 獲取簽名
            var signature = cosRes.data.sign;

            // 頭部帶上簽名,上傳檔案至COS
            var uploadTask = wx.uploadFile({
                url: cosUrl + '/' + fileName,
                filePath: filePath,
                header: {
                    'Authorization': signature
                },
                name: 'filecontent',
                formData: {
                    op: 'upload'
                },
                success: function (uploadRes) {
                    // 上傳成功後的操作
                    var upload_res = JSON.parse(uploadRes.data)
                    var files = that.data.files;
                    files.push(upload_res.data.source_url);
                    that.setData({
                        upload_res: upload_res,
                        files: files,
                        test_image: upload_res.data.source_url
                    })
                },
                fail: function (e) {
                    console.log('e', e)
                }
            });
            // 上傳進度條
            uploadTask.onProgressUpdate((res) => {
                that.setData({
                    upload_progress: res.progress
                })
                if (res.progress === 100){
                    that.setData({
                        upload_progress: 0
                    })
                }
            })
        }
    })
    return data
}複製程式碼

小程式提供了 uploadTask.onProgressUpdate() 來獲取圖片的上傳進度,這裡我將圖片的上傳進度顯示了出來。

完整程式碼參考:metis-wxapp: https://github.com/gusibi/Metis-wxapp

參考連結


最後,感謝女朋友支援。

歡迎關注(April_Louisa) 請我喝芬達
歡迎關注
歡迎關注
請我喝芬達
請我喝芬達

相關文章