前端上传的图片很占用服务器资源,因此寻找解决办法看到了七牛云的图片上传功能,由于七牛云只提供了单张图片上传的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;
}