這是小程式開發第二篇,主要介紹如何上傳圖片到騰訊雲,之所以選擇騰訊雲,是因為騰訊雲免費空間大?
準備工作
上傳圖片主要是將圖片上傳到騰訊雲物件儲存(COS)。
要使用物件儲存 API,需要先執行以下步驟:
- 購買騰訊雲物件儲存(COS)服務
- 在騰訊雲 物件儲存控制檯 裡建立一個 Bucket
- 在控制檯 個人 API 金鑰 頁面裡獲取 AppID、SecretID、SecretKey 內容
- 編寫一個請求籤名演算法程式(或使用任何一種服務端 SDK)
- 計算簽名,呼叫 API 執行操作
所以我們要做的準備工作有:
- 進入騰訊雲官網,註冊帳號
- 登入雲物件儲存服務(COS)控制檯,開通COS服務,建立資源需要上傳的Bucket
- 在小程式官網上配置域名資訊(否則無法在小程式中發起對該域名的請求)
這些配置過程這裡就不做說明了,接下來主要介紹步驟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
: 賬號的appidBUCKET_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) | 請我喝芬達 |
---|---|