阿里云官方文档:微信小程序直传实践
1、阿里云配置Bucket跨域访问、微信小程序配置域名白名单 见官方文档。
2、获取签名:使用客户端签名。需现在服务端搭建一个STS服务,然后客户端获取STS临时授权账号并生成签名。
uploadOSS.js
依赖包:crypto-js , js-base64 加密用
import crypto from 'crypto-js';
import {
Base64
} from 'js-base64';
// 统一请求接口
import unirequest from '@/utils/uni-request.js';
// 计算签名。
function computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
const date = new Date();
date.setHours(date.getHours() + 1);
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
],
};
// 业务代码(忽略)
export function checkLoading(list) {
return list[0].fpath ? list.some(val => val.fpath === '/static/loading.svg') : list.some(val => val === '/static/loading.svg')
}
// 获取签名
export async function getFormDataParams() {
const userInfo = uni.getStorageSync("user")
const {
data
} = await unirequest({
method: "get",
url: '/oss/fetchSts',
header: userInfo?.token ? {
token: userInfo.token
} : {}
})
const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。
const signature = computeSignature(data.data.accessKeySecret, policy)
const formData = {
ossAccessKeyId: data.data.accessKeyId,
signature: signature,
policy,
'x-oss-security-token': data.data.securityToken,
bucketPath: data.data.bucketPath
}
return formData
}
// 统一的Bucket访问域名或者自定义域名,看业务需求
export const bucketUrl = 'https://examplebucket.oss-cn-zhangjiakou.aliyuncs.com'
3、上传业务:
页面:
// 引入
import * as OSS from '@/utils/uploadOSS.js';
// 上传文件方法-OSS
async function getMedia(name, path, index) {
uni.showLoading({
title: '上传中'
});
const formData = await OSS.getFormDataParams();
if (formData.ossAccessKeyId) {
uni.uploadFile({
url: OSS.bucketUrl, //这个是阿里云bucket的根地址,使用这个地址拼接路径可以访问已上传的文件
filePath: path, // 本地文件路径,小程序chooseImage方法返回的路径
name: 'file', // 必须填file
formData: {
...formData,
key: `${formData.bucketPath}${name}`
},
success: (res) => {
if (res.statusCode === 204) {
uni.showToast({
title: '上传成功',
icon: 'none'
});
// 具体业务
console.log('-------------success------------');
const fileUrl = `${OSS.bucketUrl}/${formData.bucketPath}${name}`;
imageList.value[index].fpath = fileUrl
} else if (res.statusCode === 403) {
uni.showToast({
title: '网络超时',
duration: 2000
});
} else {
console.log('上传失败');
}
},
fail(err) {
console.error('uni.uploadFile: fail', err);
}
});
}
}