laf icon indicating copy to clipboard operation
laf copied to clipboard

客户端直连OSS 则uni.uploadFile 不支持PUT?

Open hankeke opened this issue 3 years ago • 1 comments

微信环境(小程序|APP)是不支持PUT请求

解决方案

  • 允许给POST请求的presigned URL设置策略

云函数 get-oss-sign-url

  import cloud from '@/cloud-sdk'
  const Minio = require('minio')
  
  const uriRegExp = new RegExp('^(http://|https://)?(\\S+)')
  exports.main = async function (ctx: FunctionContext) {
    const { fileName, bucketName } = ctx.body
    return await signUrl(fileName,bucketName)
  }
  
  function splitURL(val?: string) {
    return uriRegExp.exec(cloud.env.OSS_EXTERNAL_ENDPOINT)[2]  
  }
  
  // 签名方法
  function signUrl(fileName: string,bucketName: string) {
    // minIO 配置
    const client = new Minio.Client({
      bucketName: bucketName,
      endPoint: splitURL(),
      useSSL: true,
      accessKey: cloud.env.OSS_ACCESS_KEY,
      secretKey: cloud.env.OSS_ACCESS_SECRET,
    });
    return new Promise((resolve, reject) => {
      let policy = client.newPostPolicy()
      policy.setBucket(bucketName)
      policy.setKey(fileName)
      let expires = new Date()
      // 10d
      expires.setSeconds(24 * 60 * 60 * 10);
      policy.setExpires(expires)
      client.presignedPostPolicy(policy, function (err, data) {
        if (err) return console.log(err)
          resolve(data)
      })
    })
  }
  • 使用uni上传文件

 uni.chooseImage({
        success: async (res) => {
          const tempStr = res.tempFiles[0].path;
          const tempArr = tempStr.split("/");
          const fileName = tempArr[tempArr.length - 1];
          await uploadFile(fileName, res.tempFilePaths[0]);
        },
      });
  • 上传文件

/**
 * 上传文件
 * @param filePath file
 * @param bucketName bucket
 * @returns 
 */
export async function uploadFile(
    fileName: string,
    filePath: string,
    bucketName = "15365402-1fd4-4340-a608-public"
) {
    const data = await getUrl(fileName, bucketName)
    const formData = data.formData
    const postURL =  data.postURL

    uni.uploadFile({
        url: postURL,
        filePath: filePath,
        name: "file",
        formData: formData,
        success(res) {
            console.log('上传成功了', res)
        }
    })
}

hankeke avatar Jun 16 '22 09:06 hankeke

直接使用 cloud.env.OSS_EXTERNAL_ENDPOINT 做为 endpoint 配置生成预签地址应该也是可以的,等尝试后,这块加入文档中。

maslow avatar Jun 20 '22 14:06 maslow