前端上傳的圖片很佔用服務器資源,因此尋找解決辦法看到了七牛雲的圖片上傳功能,由於七牛雲只提供了單張圖片上傳的api,我使用循環的方式實現了前端上傳多圖的效果。實現過程中踩到了兩個坑值得記錄一下,第一是循環中的異步回調函數導致的key和token錯位,其次就是回調函數的作用域問題。
前端使用的是dcloud的uniapp框架,大致結構與微信小程序沒有差別,基本上小程序的api在uniapp中也有對應的api。
前端使用
首先下載七牛雲提供的前端sdk,解壓到本地將 qiniuUploader.js 引入到需要上傳圖片的頁面使用。
這裏我放到了components/qiniuUploader目錄下。
<template>
<view>
<button type="primary" @click="qupload">選擇圖片</button>
<button type="primary" @click="test">七牛多圖</button>
</view>
</template>
<script>
const qiniuUploader = require("../../components/qiniuUploader");
export default {
data() {
return {
token: [],
key: [],
filePath: []
}
},
methods: {
qupload() {
// 選擇圖片
uni.chooseImage({
count: 4,
success: (res) => {
this.filePath = this.filePath.concat(res.tempFilePaths);
for (var i = 0; i < 4; i++) {
// this.key[i] = md5(Math.random().toString(36).substr(2));一開始是在這裏生成後端生成token所需的key,由於沒有考慮到回調函數的異步導致了key和token不匹配造成的上傳失敗,最後通過將key放到後端生成,前端請求後端接口時一起獲取解決了這個問題
uni.request({
url: 'http://api.nauzone.cn/?service=',//後端生成key和token的接口
success: (re) => {
console.log(re.data.data);
// this.token.push(re.data.data);
//將token和key放入數組中備用,這裏還有一個問題就是回調函數的this指向問題,經過經驗事實發現,如果回調函數的格式寫成匿名函數 success:function(){ }的樣式將會導致this指向變爲函數內部,這是將報this沒有token和key的屬性,雖然這已經在全局聲明瞭。寫成success: (re) => { } 則沒有任何問題,此時回調函數內部就是全局。還有一個坑也是回調函數的異步導致的在同一個執行期上下文內,在回調函數的內部push的值在外部不能立即獲取,這裏需要注意一下。
this.token.push(re.data.data.token);
this.key.push(re.data.data.key);
}
});
}
}
});
},
test() {//循環上傳圖片
for (var i = 0; i < 4; i++) {
//console.log(this.filePath[i]);
console.log(this.key[i]);
console.log(this.token[i]);
qiniuUploader.upload(this.filePath[i], (res) => {
console.log(res.imageURL);
}, (error) => {
var a = JSON.stringify(error);
console.log('error: ' + a);
}, {
region: 'ECN',
domain: 'pn7r16wx7.bkt.clouddn.com', // // bucket 域名,下載資源時用到。如果設置,會在 success callback 的 res 參數加上可以直接使用的 ImageURL 字段。否則需要自己拼接
key: this.key[i], // [非必須]自定義文件 key。如果不設置,默認爲使用微信小程序 API 的臨時文件名
// 以下方法三選一即可,優先級爲:uptoken > uptokenURL > uptokenFunc
uptoken: this.token[i],
});
}
}
}
</script>
後端token生成
七牛雲上傳要求由key生成一個上傳憑證token,token有3中方法生成並給七牛雲驗證。第一就是由其他程序生成token後在調用時將token一起上傳,第二是在前端構造一個token生成函數,第三是將後端生成token的api地址發給七牛。無論通過那種方式,都要求key和token要一一對應起來,否則將報403錯誤。
我採用的是第一種方法,由後端生成key和token發送給前端,前端接收後在調用時將收到的token和key發給七牛雲即可。後端採用phalapi開源php框架,引入了七牛雲服務器端的sdk後,重寫了一下便能引入實現了。
use App\Common\Qiniu;
/**
* 七牛圖片文件上傳
* @desc 只能上傳單個圖片文
* @return array token 返回七牛雲上傳憑證token
* @return string key 返回生成token的key
*/
public function qiniu() {
$rs = array();
$rs['key'] = md5(uniqid(microtime(true),true));//生成唯一字符串
$uploader = new Qiniu('七牛雲ak’,'七牛雲sk');
$rs['token'] = $uploader->uploadToken('upload',$rs['key']);
return $rs;
}