背景介绍
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>
效果图
