uni-app&小程序 封装阿里云OSS直传函数
前言
因为小程序端上传文件到服务器的方法与 Web 端不同,所以需要封装一个小程序直传到阿里云 OSS 的函数。
引入依赖文件
在项目中新建一个 cypto 文件夹,里面放入需要依赖的 js 文件以及暴露生成签名方法的 js 文件。 具体文件可以直接去我的 git 仓库下载下来: gitee: https://gitee.com/gong_yu_qi/applet-oss/tree/master github: https://github.com/TuJinSAMA/applet-oss 在 cypto 文件夹中有一个 upload.js 文件,是生成签名的文件,之前提到的方法也要从这个文件中暴露出去
// upload.js
const Base64 = require('./Base64.js')
require('./hmac.js')
require('./sha1.js')
const Crypto = require('./crypto.js')
// 计算签名。
function computeSignature(accessKeySecret, canonicalString) {
const bytes = Crypto.HMAC(Crypto.SHA1, canonicalString, accessKeySecret, {
asBytes: true,
})
return Crypto.util.bytesToBase64(bytes)
}
const date = new Date()
date.setHours(date.getHours() + 1)
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
['content-length-range', 0, 50 * 1024 * 1024], //限制大小 50M
],
}
export function getFormDataParams(credentials) {
const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。
const signature = computeSignature(credentials.AccessKeySecret, policy)
const formData = {
OSSAccessKeyId: credentials.AccessKeyId,
signature,
policy,
'x-oss-security-token': credentials.SecurityToken,
}
return formData
}
封装上传函数
在项目中可以新建一个 utils 工具文件夹,在里面创建 upload.js 文件,封装好上传的方法并暴露出去即可。
import { apiBusinessService } from '@/services/http/business.js'
import { getFormDataParams } from '../cypto/upload' // 这里注意路径
export function uploadFile(filePathList) {
// 先获取ossToken
// 后端需要提供一个获取OSS Token的接口
return apiBusinessService
.ossToken()
.then(({ data }) => {
return uploadFileToWx(data, getFormDataParams(data), filePathList)
})
.catch((err) => {
return new Error(err)
})
}
// 封装一个Promise 用来处理多文件依次上传
function uploadFileToWx(oss, token, filePathList) {
return new Promise((resolve, reject) => {
const promises = filePathList.reduce((arr, item) => {
const p = batchUpload(item, oss, token)
return [...arr, p]
}, [])
Promise.all(promises)
.then((list) => {
resolve(list.map((item) => item.fileUrl))
})
.catch((err) => {
reject(err)
})
})
}
// 批量上传 返回一个远程文件链接地址的集合
function batchUpload(file, oss, token) {
return new Promise((resolve, reject) => {
const url = `https://${oss.bucketName}.oss-cn-${oss.region}.aliyuncs.com`
const key = `${Date.now()}/${file.replace('wxfile://tmp_', '')}` //文件名替换前缀
// 这里是uni的api 换成微信官方的api同理
uni.uploadFile({
url,
filePath: file,
name: 'file',
formData: {
...token,
key,
success_action_status: '200', //与OSS约定好上传成功的status
},
success(res) {
if (res.statusCode !== 200) {
return reject(res)
}
res.fileUrl = url + '/' + key
res.fileName = file.replace('wxfile://tmp_', '') //文件名替换前缀
resolve(res)
},
fail(err) {
reject(err)
},
})
})
}
使用示例
// 引入封装好的函数
import { uploadFile } from '@/utils/upload/upload.js';
// 某个事件触发函数
handlePhotoUpload() {
// 以uni提供的选择图片api为示例
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 从相册选择或拍照
success: res => {
uploadFile(res.tempFilePaths).then(res => {
if (res.length > 0){
// res:[] 就是远程文件链接的集合
console.log(res);
}
});
},
});
},