小程序/uniapp使用阿里云serverless进行oss客户端签名直传实践
最近在弄小程序/uniapp使用阿里云serverless进行oss客户端签名直传,因为官方文档的示例代码瞎几把写看不明白浪费了很多时间摸索,这里记录下:
其实大概半年前用php对接过,也是很不顺利。。。
node后端代码:
const config = require('../../config');
const OSS = require('ali-oss');
module.exports = class AliOSS {
static Bucket = 'hejiu-tools';
static UrlTimeout = 600;
static getClient() {
return new OSS({
accessKeyId: config.oss.RamAK,
accessKeySecret: config.oss.RamSK,
region: config.oss.RegionId,
bucket: AliOSS.Bucket,
secure: true, // https
});
}
// 小程序端fileUpload只支持post,这个玩意强制put,弃了。
static async getSignature(fileName) {
const client = AliOSS.getClient();
const response = await client.signatureUrlV4(
'PUT', 60*1000,
{
headers: {
'content-type': 'xxx', // 默认是application/octet-stream,需要换成文件的content-type
},
}, fileName
);
return response;
}
// 表单上传签名,小程序端fileUpload只支持post上传
static async getPostPolicy() {
const client = AliOSS.getClient();
const policy = {
expiration: new Date(Date.now() + 10*60000).toISOString(), // 10分钟后过期
conditions: [
["content-length-range", 0, 104857600] // 文件大小限制100MB
]
};
const formData = client.calculatePostSignature(policy);
return {
host: `https://${AliOSS.Bucket}.${config.oss.RegionId}.aliyuncs.com`,
policy: formData.policy,
signature: formData.Signature,
OSSAccessKeyId: formData.OSSAccessKeyId,
expire: Date.now() + 600000
};
}
}
小程序前端代码:
获取签名:
// 因为后端使用了serverless,为了适应http的习惯,所以写了这个类
import MPServerless from '@alicloud/mpserverless-sdk'
import config from '../../../config/config';
export default class Serverless {
static instance;
isAuthorized = false;
constructor(){
if (!Serverless.instance) {
this.mpsl = new MPServerless({
uploadFile: uni.uploadFile,
request: uni.request,
getAuthCode: this._getAuthCode,
}, config.sl); // config.sl: serverless配置
Serverless.instance = this;
this._authorize();
}
return Serverless.instance;
}
_authorize() {
if (!this.isAuthorized) {
// 进行匿名授权
this.mpsl.init({
authorType: 'anonymous'
});
this.isAuthorized = true;
}
}
_getAuthCode(){
return new Promise(async (resolve, reject) => {
uni.login({
provider: 'weixin',
success: async (res) => {
console.log('login success:', res);
const authCode = res.code;
if(authCode) resolve(authCode);
else reject('获取授权码失败');
},
fail: (err) => {
console.log('login fail:', err);
}
})
})
}
request(url='', params={}, loading=false){
return new Promise(async (resolve, reject) => {
console.log('SL request:', url, params);
const [ n, mod, method ] = url.split('/');
if(!mod || !method) return reject('Invalid url');
loading && uni.showLoading({ title: '加载中...' });
this.mpsl.function.invoke('slapi', { module: mod, method, ...params}).then(res => {
if(res.success) resolve(res.result);
reject(res.result);
}).finally(() => uni.hideLoading());
});
}
}
// 获取签名
(new Serverless()).request('/aliCloud/getPostPolicy', {}).then(res => {
uni.hideLoading();
console.log(res);
if(res.code) return uni.showToast({ title: 'OSS服务异常,请稍重试!' });
this.uploadFile(res.data);
});
上传文件:
uploadFile(ossData={}) {
const { tempFile } = this;
const fileName = generateUUID()+`.${tempFile.extname}`;
const filePath = 'dir/'+fileName; // this.$g.tempFile.name
return uni.uploadFile({
url: config.oss.host,
name: 'file',
filePath: tempFile.path,
formData: Object.assign({key: filePath}, ossData),
success: (res) => {
console.log(res);
if(res?.statusCode >= 300) return this.$g.info('上传失败');
this.$g.info('上传成功');
this.path = config.oss.host+`/${filePath}`;
this.fileName = fileName;
// this.encodeData(fileName);
},
fail: (err) => {
// console.warn(err);
this.$g.info('上传失败');
}
});
},


浙公网安备 33010602011771号