记录下uni-app接入七牛云文件上传的流程
背景:
新项目启动需要unipp框架,前期需要先接入一些通用功能和组件。今天想实现下七牛云附件上传相关工作, 之前都是需要后端配合获取token。因为Dcloud有云函数, 所以试着脱离后端自己实现七牛云的附件上传这一功能。但是项目正式启用还是会转回后端获取, 因为感觉到不安全, 如果程序被反编译, 拿到我云函数地址不安全, 虽然可以继续在云函数做鉴权操作解决。但是想想还是太麻烦, 毕竟初涉uniapp这一领域。
需要配准备的:
- 七牛云账户 开通对象存储服务 创建空间(Bucket) 获取
AccessKey
SecretKey
(秘钥管理) - Dcloud开通云空间 uniapp项目关联绑定
实现流程:
- unaipp项目通过云函数获取七牛云上传附件token
- uniapp项目通过云函数+上传token获取附件资源地址
代码实现(开始水了):
创建云函数:
安装Node.js 七牛云 SDK
npm install qiniu
这里需要注意下 不是在你的项目根目录install 是在云函数的目录install
Node.js SDK 的所有功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access Key
和Secret Key
编辑云函数
javascript
'use strict';
const qiniu = require('qiniu');
var accessKey = 'your access key';
var secretKey = 'your secret key';
var mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
// 最简单的上传凭证只需要AccessKey,SecretKey和Bucket就可以。
var options = {
scope: bucket,
//自定义凭证有效期(示例2小时,expires单位为秒,为上传凭证的有效时间 默认有效期为1个小时)
expires: 7200,
//默认情况下,文件上传到存储之后,在没有设置returnBody或者回调相关的参数情况下,存储返回给上传端的回复格式为hash和key
//{"hash":"Ftgm-CkWePC9fzMBTRNmPMhGBcSV","key":"qiniu.jpg"}
// returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}',
};
var putPolicy = new qiniu.rs.PutPolicy(options);
var uploadToken=putPolicy.uploadToken(mac);
exports.main = async (event, context) => {
//event为客户端上传的参数
// console.log('event : ', event)
//返回数据给客户端
return {
code: 10000,
message: '获取token成功!',
status: 'success',
token: uploadToken,
}
};
如果想更多了解SDK能力 比如覆盖上传等,请访问七牛云官方文档
接下来 右键云函数文件下上传部署
部署后前往Dcloud控制台
设置云函数请求路径
然后uniapp端就可以调用此接口获取上传附件所需的token了 可以本地运行调试一下 (右键云函数文件夹 运行本地云函数)
下面是获取token的代码
javascript
// 获取七牛云文件上传token
getQiniuToken: () => {
return new Promise((resolve, reject) => {
uni.request({
url: 'https://fc-xx-xxxxxxxxx.next.xxxx.com/qiniuUploadToken',
method: 'POST',
success: (res) => {
resolve(res.data);
},
fail: (error) => {
console.log('获取token失败:', error);
reject(error);
},
});
});
}
ini
// 获取七牛云上传附件token
async function getQiniuToken() {
let result = await core.$api.app.getQiniuToken();
state.uploadToken = result.token;
}
服务端直传
服务端直传是指客户利用服务端SDK从服务端直接上传文件到存储,交互的双方一般都在机房里面,所以服务端可以自己生成上传凭证,然后利用SDK中的上传逻辑进行上传,最后从存储服务获取上传的结果,这个过程中由于双方都是业务服务器,所以很少利用到上传回调的功能,而是直接自定义returnBody
来获取自定义的回复内容。
javascript
// 七牛文件上传
uploadQiniu: (file, token, callback) => {
// 防止附件名称重复 先拿到时间戳在附件后缀
// 如果你想上传到指定目录(空间下可以创建文件夹方便归类) 可以拼接目录到key上 例如下面的uniapp
const fileExtension = file.split('.').pop();
const key = 'uniapp/' + new Date().getTime() + '.' + fileExtension;
uni.showLoading({
title: '上传中',
});
return new Promise((resolve, reject) => {
console.log(file);
uni.uploadFile({
//这里需要注意 根据你七牛云控制台设置的地域 选择对应的url, 我的是华北, 下面我会附上表格!
url: 'https://upload-z1.qiniup.com',
filePath: file,
name: 'file',
formData: {
'key': key,
'token': token,
},
// 存成功后的回调
success: (uploadFileRes) => {
let key = JSON.parse(uploadFileRes.data).key;
// 七牛云控制台你配置的文件域名 + key就是文件的访问地址
const img_url = 'https://xxxx.xxx.com/' + key;
uni.hideLoading();
resolve(img_url);
},
fail: (err) => {
console.log('上传失败了', err);
uni.hideLoading();
reject(err); // 失败时调用 reject 返回错误信息
}
});
});
},
存储区域 | 地域简称 | 上传域名 |
---|---|---|
华东 | z0 | 服务器端上传:http(s)://up.qiniup.com |
华东 | z0 | 客户端上传: http(s)://upload.qiniup.com |
华北 | z1 | 服务器端上传:http(s)://up-z1.qiniup.com |
华北 | z1 | 客户端上传: http(s)://upload-z1.qiniup.com |
华南 | z2 | 服务器端上传:http(s)://up-z2.qiniup.com |
华南 | z2 | 客户端上传: http(s)://upload-z2.qiniup.com |
北美 | na0 | 服务器端上传:http(s)://up-na0.qiniup.com |
北美 | na0 | 客户端上传: http(s)://upload-na0.qiniup.com |
东南亚 | as0 | 服务器端上传:http(s)://up-as0.qiniup.com |
东南亚 | as0 | 客户端上传: http(s)://upload-as0.qiniup.com |
ini
// 头像上传
async function uploadAvatar(tempUrl) {
if (!tempUrl || state.uploadToken === '') return;
let url = await core.$api.app.uploadQiniu(tempUrl, state.uploadToken);
state.avatar = url;
}
结果