阿里云 OSS 使用笔记

Web 直传

修改upload.js 的密钥和地址即可

小程序直传 (uniapp版)

从上面web直传的请求参数中拿到直传OSS必须的一些参数 (policy, OSSAccessKeyId, signature):

在 uni-app 开发的小程序中的测试代码如下:

// 生成随机字符串
generateMixed (len) {
  const time = new Date().getTime().toString()
  const date = moment().format("YYYYMMDDhhmmss");
  const chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
  var res = "";
  for (var ia = 0; ia < len ; ia ++) {
    var id = Math.ceil(Math.random() * (chars.length - 1));
    res += chars[id];
  }
  return date + res + time;
}
// 直传OSS
uploadToOSS () {
  const url = 'http://xxx.oss-cn-shenzhen.aliyuncs.com'
  const policy = 'xxx'
  const OSSAccessKeyId = 'xxx'
  const signature = 'xxx'
  const filename = generateMixed(32) // 生成32为的随机文件名
  const vm = this
  return new Promise((resolve, reject) => {
      uni.chooseImage({
        count: 1,
        success (res) {
          const tempFileNameArr = res.tempFilePaths[0].split('.')
          const ext = tempFileNameArr[tempFileNameArr.length - 1]
          vm.loading('图片上传中...')
          uni.uploadFile({
            url,
            filePath: res.tempFilePaths[0],
            name: 'file',
            formData: {
              'key' : `imgs/${filename}.${ext}`,
              'success_action_status' : '200',
              policy, OSSAccessKeyId, signature
            },
            success (uploadFileRes) {
              let filepath = `${url}/imgs/${filename}.${ext}`
              if (uploadFileRes.statusCode) {
                uni.hideLoading()
                vm.toast('上传成功!', 'success')
                resolve(filepath);
              } else {
                reject();
              }
            },
            fail (e) {
              vm.toast('上传失败!')
              reject();
            }
          });
        }
      });
  })
}

Browser.js 直传

凡是使用 npm/yarn 包管理工具管理依赖的项目, 都可以使用此方式进行上传, 首先安装 ali-oss

安装:

yarn add ali-oss

简单上传:

let OSS = require('ali-oss');
let client = new OSS({
  region: '<Your region>',
  accessKeyId: '<Your AccessKeyId>',
  accessKeySecret: '<Your AccessKeySecret>',
  bucket: 'Your bucket name'
});
async function putBlob () {
  try {
    let result = await client.put('object-key', new Blob(['content'],{ type: 'text/plain' }));
    console.log(result);
  } catch (e) {
    conosle.log(e);
  }
}
putBlob();

断点续传:

let OSS = require('ali-oss')
let ossConfig = {
  region: '<Your region>',
  accessKeyId: '<Your AccessKeyId>',
  accessKeySecret: '<Your AccessKeySecret>',
  bucket: 'Your bucket name'
}
let client = new OSS(ossConfig);
let tempCheckpoint;
// 定义上传方法
async function multipartUpload () {
  try {
    let result = await client.multipartUpload('object-key', 'local-file', {
      progress: async function (p, checkpoint) {
        // 记录断点, 如果关闭了浏览器,然后重新启动继续上传的话,是不行的,请参考上边对file对象的描述
        tempCheckpoint = checkpoint;
      }
      meta: { year: 2017, people: 'test' },
      mime: 'image/jpeg'
   })
  } catch(e){
    console.log(e);
  }
}
//开始上传
multipartUpload();
// 暂停分片上传方法
client.cancel();
// 恢复上传
let resumeclient = new OSS(ossConfig);
async function resumeUpload () {
  try {
    let result = await resumeclient.multipartUpload('object-key', 'local-file', {
      progress: async function (p, checkpoint) {
          tempCheckpoint = checkpoint;
        },
        checkpoint: tempCheckpoint
        meta: { year: 2017, people: 'test' },
        mime: 'image/jpeg'
      })
  } catch (e) {
    console.log(e);
  }
}
resumeUpload();

封装 (使用分片上传):

import OSS from 'ali-oss';
const ossRegion = 'oss-cn-shenzhen'
const ossEndpoint = 'https://xxx.oss-cn-shenzhen.aliyuncs.com'
const ossAK = 'xxx'
const ossAS = 'xxx'
const ossBucket = 'xxx'
class Utils {
  // 上传到 OSS
  async uploadToOss (file, fileList, type) {
    const ext = file.name.split('.').pop()
    const fileName = this.generateMixed(32) + '.' + ext
    let client = new OSS({
      cname: true,
      secure: true,
      region: ossRegion,
      endpoint: ossEndpoint,
      accessKeyId: ossAK,
      accessKeySecret: ossAS,
      bucket: ossBucket
    });
    try {
      let res = await client.multipartUpload("res/" + fileName, file.raw, {
        progress: async function (p, checkpoint) {
          console.log(p, checkpoint)
        }
      });
      return {...res, type, url: ossEndpoint + '/' + res.name}
    } catch (e) {
      throw new Error(e)
    }
  }
  // 生成随机字符串
  generateMixed (len) {
    const time = new Date().getTime().toString()
    const date = this.genCurrTime();
    const chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
    let res = "";
    for (let ia = 0; ia < len ; ia ++) {
      let id = Math.ceil(Math.random() * (chars.length - 1));
      res += chars[id];
    }
    return date + res + time;
  }
  // 生成当前时间, 格式 20180101126060
  genCurrTime () {
    return this.formatTime(new Date(), true, '', '', '')
  }
  // 格式化时间
  formatTime (date = new Date(), withTime = true, split1 = '-', split2 = ':', splite3 = ' ') {
    const showDate = [date.getFullYear(), date.getMonth() + 1, date.getDate()]
      .map(n => n.toString()[1] ? n : '0' + n).join(split1)
    const showTime = [date.getHours(), date.getMinutes(), date.getSeconds()]
      .map(n => n.toString()[1] ? n : '0' + n).join(split2)
    return withTime ? showDate + splite3 + showTime : showDate
  }
}
const utils = new Utils()
export default utils

阿里OSS基本配置

样式处理

阿里云OSS的样式处理类似,使用的时候使用以下规则即可访问

# 默认规则
域名/sample.jpg?x-oss-process=style/stylename
# 自定义规则
域名/sample.jpg自定义分隔符stylename

域名设置

由于我的域名管理也在阿里云里面,因此使用起来感觉更方便些

排错

错误: InvalidPart

InvalidPart: One or more of the specified parts could not be found or the specified entity tag might not have matched the part's entity tag.

错误详细

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>InvalidPart</Code>
  <Message>One or more of the specified parts could not be found or the specified entity tag might not have matched the part's entity tag.</Message>
  <RequestId>5877284DE7D217CB1B39C200</RequestId>
  <HostId>dxt-brand.oss-cn-shanghai.aliyuncs.com</HostId>
  <ETag>undefined</ETag>
  <PartNumber>1</PartNumber>
  <UploadId>1FC722E82639475EB26E5D2A73A4F543</UploadId>
</Error>

解决方案:

在跨域设置里面的暴露 Headers 增加一条ETag

参考资料

阿里云文档

SDK

常见错误排除

阿里云OSS参考

转码作业

CDN

相关工具


MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress