OSS 上传配置

124 阅读1分钟

什么是OSS?

阿里云对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

安装

  • 通过 CDN 引入
<!-- 引入在线资源 -->
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-4.4.4.min.js"></script>
  • 通过 npm 安装
$ npm install ali-oss -S

注意:使用npm引入时,需要在使用的位置引入OSS

let OSS = require('ali-oss');

初始化OSS

const config = {
    accessKeyId: 'your access key',
    accessKeySecret: 'your access secret',
    stsToken: '使用临时授权方式',
    endpoint: 'OSS域名',
    bucket: 'your bucket name',
    secure: true // true 使用 HTTPS, false 使用 HTTP
}

const client = new OSS.Wrapper(config)

if (!client) {
    alert('OSS 初始化失败,无法上传!')
    return
}

以上配置参数,需由后端提供。

为了安全性,accessKeyId 和 accessKeySecret 不存储于前端。且需要 stsToken 临时 token 授权。

简单上传

// 支持File对象、Blob数据以及OSS Buffer。
const data = '<File Object>';
// or const data = new Blob('content');
// or const data = new OSS.Buffer('content'));

async function putObject () {
  try {
    // object-key可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
    let result = await client.put('object-key', data);
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}
putObject();

分片上传

大文件可采用分片上传,并且能够获取到上传进度。

const tempCheckpoint = {} // 分片续传的位置
    multipartUpload(tempCheckpoint)
    async function multipartUpload(tempCheckpoint) {
    try {
        const results = await client.multipartUpload(fileName, file, {
            progress: (percentage, checkpoint) => {
                tempCheckpoint = checkpoint // 断点位置
                if (tempCheckpoint) { // 未传完,则继续上传
                    multipartUpload(tempCheckpoint)
                }
                progressCallback && progressCallback(percentage) // 进度的回调函数
            },
            checkpoint: tempCheckpoint
        })
        uploadResponse(results) // 上传完成
    } catch (e) {
        console.log(e)
    }
}

// 上传返回
function uploadResponse(results) {
    let fileUrl = ''
    if (results.url) {
        fileUrl = results.url
        callback && callback(fileUrl) // 成功回调
    } else if (results.res.requestUrls) {
        const result = results.res.requestUrls
        if (result[0].indexOf('?') !== -1) {
            fileUrl = result[0].slice(0, result[0].indexOf('?'))
        } else {
            fileUrl = result[0]
        }
        callback && callback(fileUrl) // 成功回调
    } else {
        Vue.$message.error('上传失败')
    }
}

完整代码如下

import Vue from 'vue'
import moment from 'moment'
import md5 from 'md5'
import { getStsTokenAPI } from '@/api/upload'

/**
 * @description: 上传文件至 OSS
 * @param {*} type 获取 OSS 文件前缀
 * @param {*} file 需要上传的文件
 * @param {*} progressCallback 进度的回调函数
 * @param {*} callback 上传成功的回调函数
 */
const uploadFileToServer = (type, file, progressCallback, callback) => {
  getStsTokenAPI({ type })
    .then(res => {
      // eslint-disable-next-line
      const config = {
        accessKeyId: res.data.AccessKeyId,
        accessKeySecret: res.data.AccessKeySecret,
        stsToken: res.data.SecurityToken,
        endpoint: 'https://' + res.data.endpoint,
        bucket: res.data.bucket,
        secure: true
      }
      const client = new OSS.Wrapper(config)

      if (!client) {
        Vue.$message.error('OSS 初始化失败,无法上传!')
        return
      }
      const name = md5(file.name + moment().valueOf()) + getSuffix(file.name) // 文件名
      const catalog = res.data.upload_type_prefix // 目录
      const fileName = catalog + name

      // 图片整传
      if (type === 10) {
        client.multipartUpload(fileName, file)
          .then(results => {
            uploadResponse(results)
          })
      } else { // 如果是音频和视频采用断点续传
        const tempCheckpoint = {} // 分片续传的位置
        multipartUpload(tempCheckpoint)
        async function multipartUpload(tempCheckpoint) {
          try {
            const results = await client.multipartUpload(fileName, file, {
              progress: (percentage, checkpoint) => {
                console.log(percentage)
                tempCheckpoint = checkpoint
                if (tempCheckpoint) {
                  multipartUpload(tempCheckpoint)
                }
                progressCallback && progressCallback(percentage) // 进度的回调函数
              },
              checkpoint: tempCheckpoint
            })
            uploadResponse(results)
          } catch (e) {
            console.log(e)
          }
        }
      }

      // 上传返回
      function uploadResponse(results) {
        let fileUrl = ''
        if (results.url) {
          fileUrl = results.url
          callback && callback(fileUrl) // 成功回调
        } else if (results.res.requestUrls) {
          const result = results.res.requestUrls
          if (result[0].indexOf('?') !== -1) {
            fileUrl = result[0].slice(0, result[0].indexOf('?'))
          } else {
            fileUrl = result[0]
          }
          callback && callback(fileUrl) // 成功回调
        } else {
          Vue.$message.error('上传失败')
        }
      }
    })
}

/**
 * @description: 获取文件后缀名
 * @param {String} 文件名
 */
function getSuffix(filename) {
  const pos = filename.lastIndexOf('.')
  let suffix = ''
  if (pos !== -1) {
    suffix = filename.substring(pos)
  }
  return suffix
}

export default uploadFileToServer

参考

OSS文档