Vue+Element UI分段上传(华为云obs、阿里云oss)

1,145 阅读1分钟

前端华为云obs上传文件

  1. 下载SDK BrowserJS(esdk-obs-browserjs  3.21.8)
  2. index.html文件中引入文件
<script src="<%= BASE_URL %>static/obs/obsjs/@cloud/esdk-obs-browserjs-without-polyfill-3.21.8.min.js"></script>
  1. 实例化new ObsClient()传入参数
<template>
  <el-upload
      class="avatar-uploader"      
      action
      :show-file-list="false"
      :http-request="handleUpload"
      :before-upload="beforeAvatarUpload">
          <img v-if="imageUrl" :src="imageUrl" class="avatar">
          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  </el-upload>
</template>

<script>
export default {
    data() {
        return {
            imageUrl: '',
            initiateData: {
                option: {},
                uploadId: ''
            },
            fileUrl: ''
        }
    },
    create() {
        this.obsClient = new ObsClient({
            access_key_id: '',
            secret_access_key: '',
            server: '',
            obsClient: ''
        })
    },
    methods: {
        beforeAvatarUpload() {
            const isJPG = file.type === 'image/jpeg';
            const isLt2M = file.size / 1024 / 1024 < 2;
            if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!');
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!'); 
            }
            return isJPG && isLt2M;
        },
        handleUpload(option) {
            this.initiateData.option = option;
            this.fileUrl = ''
            var _this = this
            const params = {
                Bucket: '',
                Key: this.fileUrl
            }
            this.obsClient.initiateMultipartUpload(params)
                .then((result) => {
                    if (result.CommonMsg.Status < 300) {
                        var uploadId = result.InterfaceResult.UploadId;
                        _this.initiateData.uploadId = uploadId;
                        /*
                         * Step 2: upload a part
                         */
                         var etag = []
                         var uploadPromise = new Promise((resolve) => {
                             var partLen = 5 * 1024 * 1024
                             var count = Math.ceil(option.file.size / partLen)
                             var indexNum = 0
                             this.uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve)
                         })
                         uploadPromise.then((result) => {
                             const paramsEnd = {
                                 Bucket: '',
                                 Key: this.fileUrl,
                                 UploadId: uploadId,
                                 Parts: etag.sort((a,b)=>a.PartNumber-b.PartNumber)
                             }
                             this.obsClient.completeMultipartUpload(paramsEnd)
                                 .then((result) => {
                                     if (result.CommonMsg.Status < 300) {
                                         _this.getImageUrl(option.file, option);
                                     }
                                 })
                         })
                    }
                })
        },
        uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve) {
            var _this = this
            this.obsClient.uploadPart({
                Bucket: '',
                Key: this.fileUrl,
                UploadId,
                PartNumber: indexNum + 1, 
                SourceFile: option.file,
                PartSize: partLen,
                Offset: partLen * indexNum,
            })
            .then((result) => {
                etag.push({
                    ETag: result.InterfaceResult.ETag,
                    PartNumber: indexNum + 1,
                })
                indexNum ++;
                if (indexNum < count) {
                    _this.percentage = Math.ceil(indexNum/count*100)
                    option.file.percent = _this.percentage
                    option.onProgress(option.file)
                    _this.uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve)
                 }
                 if (indexNum == count) {
                    _this.percentage = 100
                    option.file.percent = _this.percentage
                    option.onProgress(option.file)
                    resolve("任务完成");
                  }
            })
        },
        getImageUrl(objName, option) {
            const _this = this;
            this.obsClient.getObject({
                Bucket: '',
                Key: '',
                SaveByType: 'file'
            }, function(error, response) {
                if (error) {
                } else if (response.CommonMsg.Status < 300) {
                    const url = response.InterfaceResult.Content.SignedUrl
                    this.imageUrl = url
                }
            })
        }
    }
}
</script>

前端阿里云oss上传文件

安装依赖

npm install ali-oss

引入ali-oss

const OSS = require('ali-oss')

实例化new OSS()传入参数

<template>
  <el-upload
    action
    :http-request="handleUpload"
    accept="*"
    :show-file-list="false"
    :on-remove="onRemoveList"
  >
    <div>
      <el-progress
        v-if="percentage && !imgFile"
        type="circle"
        :percentage="percentage"
        class="progress"
        :width="100"
      />
      <img v-if="imgFile" ref="img" :src="imgFile" style="width:100px;height:100px;" class="avatar">
      <i v-else class="el-icon-plus img-uploader-icon" />
    </div>
    <div v-show="tips" class="font-red">{{ tips }}</div>
  </el-upload>
</template>

<script>
const OSS = require('ali-oss')

export default {
  data() {
    return {
      // 进度条
      percentage: 0,
      // 提示
      tips: '',
      // 图片url
      imgFile: '',
      tempCheckpoint: '',
      clientObj: ''
    }
  },
  methods: {
    /**
     * 获取文件后缀名
     */
    getFileName(name) {
      const nameArr = name.split('.')
      const len = nameArr.length
      return len ? nameArr[len - 1] : ''
    },
    /**
     * 开始分片上传。
     * 上传文件,大小不能超过5GB
     * @param {string} ObjName OSS的储存路径和文件名字
     * @param {string} fileUrl 本地文件
     * @param {object} options 配置选项
     * @param {function} fn 进度条回调
     * @retruns Promise
     */
    async multipartUpload(ObjName, fileUrl, options, fn) {
      try {
        options = {
          ...options,
          progress: (p, checkpoint) => {
          // 断点记录点。浏览器重启后无法直接继续上传,您需要手动触发上传操作。
            this.tempCheckpoint = checkpoint
            fn(p, checkpoint)
          }
          // meta: { year: 2020, people: 'test' }
          // mime: 'image/jpeg'
        }
        const config = {
          secure: '',
          region: '',
          accessKeyId: '',
          accessKeySecret: '',
          bucket: '',
          stsToken: ''
        }
        const client = new OSS(config)
        console.log(client, 'client')
        this.clientObj = client
        const result = await client.multipartUpload(`${ObjName}`, fileUrl, options)
        return result
      } catch (e) {
        console.log(e)
        return e
      }
    },
    /**
     * 自定义上传方法
     */
    handleUpload(option) {
      // 生成的文件名,保留文件后缀名,进行拼接

      this.multipartUpload(option.file.name, option.file, {
        headers: {
          'Content-Disposition': 'inline',
          'Content-Type': this.getFileName(option.file.name) // 注意:根据图片或者文件的后缀来设置
        }
      }, (p, checkpoint) => {
        this.percentage = Math.ceil(p * 100)
        option.file.percent = this.percentage
        option.onProgress(option.file)
      }).then(res => {
        // console.log(res)
        if (res.name === 'cancel') return
        if (res === 'error') {
          option.onError(res)
        } else {
          this.getImageUrl(option.file.name, option)
        }
      })
    },
    // 上传成功之后,转换真实的地址
    async signatureUrl(ObjName) {
      try {
        const result = await this.clientObj.signatureUrl(`${ObjName}`)
        return result
      } catch (e) {
        console.log(e)
      }
    },
    // 获取上传完显示图片 url
    getImageUrl(objName, option) {
      objName ? this.signatureUrl(objName)
        .then(res => {
          option.onSuccess(res)
          this.imgFile = res
          this.tips = ''
        })
        : this.$message.error('发生未知错误')
    },
    // 删除文件
    onRemove() {
      this.imgFile = ''
      this.tips = ''
      this.clientObj && this.clientObj.cancel()
    },
    // 删除文件
    onRemoveList() {
      this.onRemove()
    }
  }
}
</script>