微信小程序开发工具内部有云开发功能,可以很方便的使用腾讯云空间和云数据库,但是当我们将小程序移植到安卓App时,原先的腾讯云函数就全部失效了,我们需要找一个新的云端,经过比较,阿里云以其廉价且容易申请成为为App提供云端支持的首选。
PC端使用阿里云
若是PC端使用阿里云,属于后端调用,可以直接使用npm安装ali-oss,然后在后端建立OSS对象调用相关API,非常简便,示例:
import OSS from 'ali-oss';
//相关函数
initOSS() {
let OSS_INFO = require('./cfg.js'); //cfg中存储阿里云提供的相关参数
let client = new OSS({
region: OSS_INFO.OSS_region, //区域CDN
accessKeyId: OSS_INFO.OSS_accessKeyId, // ID
accessKeySecret: OSS_INFO.OSS_accessKeySecret, //密钥
bucket: OSS_INFO.OSS_bucket //数据表名称
});
return client;
},
async delWeibo() {
let client = await this.initOSS();
let delList=['item src','item src']
let m = await client.deleteMulti(delList); // OSS delete
},
安卓端使用阿里云
上述方案可以在程序拥有后端支持使用,但是由于安卓在打包时有500K的包限制,无法将ali-oss打包进入App,所以我们必须使用前端签名的方法调用阿里云。
1. 阿里云前端签名
出于安全性考虑,前端无法获取阿里云密钥accessKeySecret
,我们采用的方法是在前端用accessKeyId将内容进行签名后发送给后端,然后后端在执行同样的签名动作进行验证,验证通过后云端开放。下面是前端执行签名的过程:
import OSS from 'ali-oss';
const crypto = require("crypto")
// 函数中
async uploadOneByOne(cloudImgUrls, imgPaths, successUp, count, length) {
let OSS_INFO = require('./cfg.js')
const policyString = JSON.stringify(OSS_INFO.OSS_POLICY)
let base64Policy = Buffer.from(policyString).toString('base64')
const signature = crypto.createHmac('sha1',OSS_INFO.OSS_accessKeySecret).update(base64Policy).digest("base64")
let cloudUrl=OSS_INFO.OSS_BASE+'/'+'weibo/'+openId+userMsgId + '-' + count
uni.uploadFile({
url: OSS_INFO.OSS_BASE, //云端根路径
filePath, //本地待上传文件缓存路径
name: 'file', //name为必填项,用来标识文件类型
formData: { //请求报文body中额外添加的字段
'key': 'weibo/'+openId+userMsgId + '-' + count, // 云端文件名
'policy': base64Policy, // 云端存储策略,必须为base64格式
'OSSAccessKeyId': OSS_INFO.OSS_accessKeyId, // 云端keyId
'signature': signature, // 刚刚生成的签名
'success_action_status': '200',
// 将返回http状态码设置成200,不写这行默认返回204状态
},
method:'put', //注意阿里云使用的是RESTful标准,上传要用put,删除用delete
success: (res) => {
cloudImgUrls.push({fileID:cloudUrl}) //兼容腾讯云的写法,阿里云可自定义
uni.showToast({
title: '上传成功',
icon: 'success',
duration: 1000
})
successUp++
},
complete: function (e) {
count++; //下一张
if (count == length) {
console.log('上传图片成功' + successUp );
that.addIntoDB(cloudImgUrls) //上传数据库,更新虚拟dom
} else {
//递归调用,上传下一张
that.uploadOneByOne(cloudImgUrls, imgPaths, successUp, count, length);
console.log('正在上传第' + count + '张', cloudImgUrls);
}
}
});
}
这里的OSS_POLICY是一个类似下面的对象,里面定义了云端过期时间和云端表名,OSS_BASE是指云端路径,而cloudUrl则是根据用户的openId,信息Id:userMsgId 以及随机数count来为云端生成唯一的url
OSS_BASE: "http://ancient-mall.oss-cn-guangzhou.aliyuncs.com",
OSS_POLICY: {
"expiration": "2050-12-01T12:00:00.000Z",
"conditions": [{
"bucket": "ancient-mall"
},
]
},
2. blob格式转换
云端OSS数据库对数据大小是很敏感的,一般要使用blob二进制来存储,而且blob格式还能有效防止爬虫盗链。小程序为了降低开发门槛,将操作数据对象的API全部做了封装,在用户手机里转成blob链接上传云端,所以腾讯云接受的都是blob格式的数据。但是阿里云OSS接收png,jpg,mp4等传统数据对象格式,在接收后由阿里云统一进行转码。
由于使用uni中Api生成的数据都是可以在腾讯云直接使用的blob:http://
格式,所以这里我们就要解决数据转码问题,思路就是拿到blob连接后将其转码成Blob或者Buffer二进制数据,转换代码如下:
dataURLtoBlob(dataurl){
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
},
如果图片是base64格式,我们可以使用格式基数的方法生成Buffer
const buffer = Buffer.from(base64, 'base64')
类似的还有
const m=parseInt("1f",16) //m=31
网友评论