oss批量上传

5,582 阅读2分钟

背景介绍

oss目前并没有官方的SDK可以批量上传文件,官方推荐的几种批量上传文件方式

  • OSSimport工具:支持从服务器本地、第三方云存储(S3、Azure、腾讯COS等)、OSS某Bucket等数据源批量上传到OSS,特别适合数据量很大的情况
  • OSSUtil工具:使用OSSUtil cp命令上传文件到OSS,通过-r(—recursive)选项,将指定路径(比如文件夹)的文件,循环递归地都上传到OSS
  • OSSBrowser工具:使用OSSBrowser工具,将文件夹批量上传到OSS
  • OSS网页控制台:您可以使用控制台,将文件夹批量上传到OSS
    文档

自行改造

  • 思路一 将文件上传的操作变成多线程的,利用线程池进行批量上传
  • 思路二 遍历选择的所有文件,一个个上传文件,直至所有文件被上传完成。

前端方案及问题

这里放在前端处理多文件上传,采用思路二。
实现过程中发现存在问题是,当遍历文件,for循环体内发起文件上传请求时,文件大小不一样,导致完成的时间有差异,由于是ajax请求是异步,导致接口回调传回的图片顺序和上传时想要的顺序不一致。
配合es6async/await,使请求变成同步。

代码

采用vue+element

  • vue文件模板
  • js部分关键处
    ####完整代码
<template>
  <div class="upload-container">
    <el-upload
      ref="upload"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :limit="150"
      :on-exceed="handleExceed"
      :action="URL+'/commonUtil/uploadFile'"
      :auto-upload="false"
      :on-change="uploadChange"
      :http-request="fnUploadRequest"
      :file-list="fileList"
      list-type="picture-card"
      class="upload-demo"
      multiple>
      <el-button slot="trigger" size="small" type="text">选取文件</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" class="uploadOssBtn" @click="handleSubmitUpload">上传到服务器</el-button>
    </el-upload>
    共{{ allNum }}个文件,上传完成第{{ uploadNum }}个文件
  </div>
</template>

<script>
import { upload } from '@/api/article'
export default {
  name: 'EditorImgListUpload',
  props: {
    closeDialog: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      dialogVisibless: false,
      fileList: [],
      uploadNum: 0,
      allNum: 0,
      uploadFileList: [],
      loading: false,
      responeList: [],
      limit: 150
    }
  },
  watch: {
    closeDialog: function(newVal, oldVal) {
      if (newVal) {
        this.uploadFileList = []
        this.fileList = []
        this.responeList = []
        this.uploadNum = 0
        this.allNum = 0
      }
    }
  },
  methods: {
    handleRemove(file, fileList) {
      console.log('删除')
      console.log(file, fileList)
      this.fileList = fileList
      this.allNum = fileList.length
    },
    handleExceed(files, fileList) {
      // const limit = this.limit
      this.$message.warning(`当前限制选择 150 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
    },
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${file.name}?`)
    },
    uploadChange(file, fileList) {
      this.fileList = fileList
      this.allNum = fileList.length
    },
    async handleSubmitUpload(e) {
      await this.$refs.upload.submit()
      this.uploadoss()
    },
    async uploadoss() {
      this.loading = true
      var length = this.uploadFileList.length
      for (let i = 0; i < length; i++) {
        const formData = new FormData()
        formData.append('file', this.uploadFileList[i].file)
        formData.append('filedir', 'test')
        await upload(formData).then(response => {
          if (response.data.code === 200) {
            this.uploadNum++
            this.responeList.push({ url: response.data.data })
            if (this.uploadNum === this.allNum) {
              this.loading = false
              this.$notify({
                title: '上传完成',
                message: '提示消息',
                type: 'success'
              })
              this.$emit('successUpload', this.responeList)
            }
          } else {
            this.$notify({
              title: '上传失败,请重新上传',
              message: '提示消息',
              type: 'warning'
            })
            this.loading = false
          }
        })
      }
    },
    fnUploadRequest(res) {
      console.log('file', res)
      this.uploadFileList.push(res)
    }
    // handleSubmit(res) {
    //   this.$emit('successCBK', this.responeList)
    // }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  .editor-slide-upload {
    margin-bottom: 20px;
    /deep/ .el-upload--picture-card {
      width: 100%;
    }
  }
  .uploadOssBtn{
    display: block;
    margin: 20px 0px!important;
  }
  .upload-demo{
    max-height: 530px;
    overflow: scroll;
    overflow-x: hidden;
  }
  ::-webkit-scrollbar-track { background-color: rgba(0,0,0,0.2);  }
  ::-webkit-scrollbar {  width: 0px;height:8px;  background-color: #F5F5F5;border-radius: 5px;  }
  ::-webkit-scrollbar-thumb { /* */background: #0C4EA2;border-radius: 5px; }
  ::-webkit-scrollbar-corner{ background-color: #F5F5F5;}
  html {
    -ms-overflow-style:none;
    overflow:-moz-scrollbars-none;
  }
  html::-webkit-scrollbar{width:0px}
</style>

效果图