概述:使用vue3+uniapp开发微信小程序,封装的一个hooks,专用来直传到ali oss的
1.引入各种依赖和函数
import { getSts } from '@/service/index/material'
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
const ossUrl = 'https://yunban-magic-box.oss-cn-beijing.aliyuncs.com'
// 生成uuid的函数
const generateUUID = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
}
2.上传函数本体
/**
* 上传文件到OSS
* @param tempFiles 临时文件列表,包含文件类型、大小和临时文件路径
* @param callBack 上传完成后的回调函数,参数为上传结果
* @param options 上传选项,包含最大文件大小和上传类型(图片用'/image/',视频用'/video/ ',音频用'/audio/')
*/
export default function useOssUpload<T = string[]>(
tempFiles: { fileType: string; size: number; tempFilePath: string }[],
callBack: (success: boolean, result?: T, err?: any) => void,
options?: { maxSize?: number; upType?: string },
) {
const uploadFileToOSS = async () => {
try {
// 1. 获取阿里云STS认证信息
const stsResponse = await getSts()
if (!stsResponse.data) {
throw new Error('获取阿里云STS信息失败')
}
const signatureParams = {
policy: stsResponse.data.policy,
'x-oss-signature-version': stsResponse.data.x_oss_signature_version,
'x-oss-credential': stsResponse.data.x_oss_credential,
'x-oss-date': stsResponse.data.x_oss_date,
'x-oss-signature': stsResponse.data.signature,
'x-oss-security-token': stsResponse.data.security_token,
success_action_status: '200',
}
const resultList: string[] = []
// 2. 上传文件到OSS
const uploadInOrder = async (file: {
fileType: string
size: number
tempFilePath: string
}) => {
return new Promise((resolve) => {
console.log('file', file)
const suffix = '.' + file.tempFilePath.split('.').pop() // 文件名后缀
// agent_id是用户id,传到ali oss时放到此id的文件夹内
const fileName =
userStore.userInfo.agent_id + (options.upType || '/image/') + generateUUID() + suffix // 上传文件名称
uni.uploadFile({
url: ossUrl,
filePath: file.tempFilePath,
name: 'file',
formData: {
...signatureParams,
key: fileName,
},
success: (res) => {
if (res.statusCode === 200) {
console.log('文件上传成功:', res, fileName)
resultList.push(fileName)
resolve(true)
} else {
console.error('文件上传失败:', res)
throw new Error('文件上传失败')
}
},
fail: (err) => {
console.error('上传失败:', err)
throw new Error('文件上传失败')
},
})
})
}
const uploadItems = async (
items: {
fileType: string
size: number
tempFilePath: string
}[],
) => {
for (const item of items) {
if (options?.maxSize && item.size > options.maxSize) {
throw new Error('文件过大')
}
await uploadInOrder(item)
}
}
// 3.全部上传完成后,调用回调函数
uploadItems(tempFiles).then(() => {
callBack(true, resultList as T)
})
} catch (err) {
console.error('上传失败:', err)
callBack(false, undefined, err)
}
}
uploadFileToOSS()
}
3.其他页面如何使用
const upImgList = [
{
fileType: 'image',
size: 1024,
tempFilePath: 'http://tmp/g8eLrsqW4dhSa50a1fa970c086b21f6c06985413e0d6.jpg',
},
]
useOssUpload(
upImgList,
(success, results, err) => {
console.log('上传oss结果', success, results, err)
uni.hideLoading()
if (success) {
uni.showToast({ title: '上传成功', icon: 'none' })
} else {
uni.showToast({ title: '保存失败', icon: 'none' })
}
},
{ upType: '/image/' },
)
4.阿里云官方提供的直传文档
5.阿里云官方提供的分片上传文档(目前只支持nodejs、浏览器、H5环境,不支持小程序)
如果想要在微信小程序内实现分片上传可以使用小程序的 miniprogram-file-uploader上传库 ,不过这个库需要后端提供三个接口:秒传验证、接收分块、合并分块,并不能绕过后端直传到阿里云。所以对于需要分片上传的大文件或视频需求,还是建议由后端提供接口,再使用这个库来调用。