微信小程序上传文件到ali oss方法封装,支持多文件上传

652 阅读2分钟

概述:使用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.阿里云官方提供的直传文档

如何在微信小程序环境下将文件上传到OSS

5.阿里云官方提供的分片上传文档(目前只支持nodejs、浏览器、H5环境,不支持小程序)

Browser.js分片上传

使用Node.js分片上传大文件到OSS

如果想要在微信小程序内实现分片上传可以使用小程序的 miniprogram-file-uploader上传库 ,不过这个库需要后端提供三个接口:秒传验证、接收分块、合并分块,并不能绕过后端直传到阿里云。所以对于需要分片上传的大文件或视频需求,还是建议由后端提供接口,再使用这个库来调用。