问题:项目基于vue开发,使用element上传组件,该组件在文件选取后会会默认开始上传,但是这样存在一个问题:上传任务太多可能导致部分素材上传不成功出现卡死的情况;服务器带宽不够,同时上传速度慢,影响效率。
需求:使用队列上传,按需设置一次允许上传多少文件,上传完成一个自动新增到队列中,直到全部上传完成。
队列思想图:
主要代码:
html部分
<el-upload
ref="upload"
:data="data"
accept="image/jpeg,image/gif,image/png,image/jpg,image/svg"
action="#"
list-type="picture-card"
multiple
:limit="20"
:file-list="materialList"
:http-request="customUpload"
:before-upload="beforeUpload"
:on-exceed="exceedFiles"
:on-success="handleSuccess">
</el-upload>
js部分
data() {
return {
uploadList:[], //上传队列数组
onQueue: false, //是否在上传
uploadItems: [], //正在上传的数组
uploadLen: 5, //上传文件个数限制
uploadLine: 0, //上传文件线程
};
},
watch: {
//监听上传队列数组是否有上传完的,如有则触发以下代码
uploadList (Newfile) {
//当onQueue为true也就是在上传中或者uploadList文件数组上传完为空时,不继续往下执行
if (this.onQueue === true || Newfile.length == 0 ) return
let files = [ ...Newfile ]
//判断上传文件线程是否小于设置的上传文件个数限制
if (this.uploadLine < this.uploadLen) {
let newQueueLine = this.uploadLen - this.uploadLine
//截取剩余文件放入上传数组
let index = this.uploadLine > 0? this.uploadLen - 1 : 0
this.uploadItems = files.splice(index, newQueueLine)
this.uploadLimit(this.uploadItems)
}
},
},
methods:{
//上传限制
uploadLimit(items) {
//遍历文件长度,就循环几次上传队列函数
for (let item of items) {
this.queueUpload(item)
}
},
//上传之前进行判断,如uploadList的中有该文件,则不让添加进去
beforeUpload(file) {
//队列去重
if (this.uploadList.length == 0){
return true
}
for (let item of this.uploadList) {
if (item.file.name == file.name){
return false
}
}
return true
},
//将文件push进uploadList中,此时uploadList变化,触发watch中的监听方法,开始第一次队列上传
customUpload(file) {
this.uploadList.push(file)
return false
},
//队列上传
queueUpload(file) {
this.onQueue = true
//开始上传该文件后,对应的上传文件线程+1
this.uploadLine++
let formData = new FormData()
formData.append('file', file.file)
formData.append('token', this.data.token)
axios({
url: this.url,
method: 'post',
data: formData,
onUploadProgress: (progressEvent) => {
let num = progressEvent.loaded / progressEvent.total * 100 | 0
if (num >= 96.9){
num = 96.9
}
file.onProgress({percent: num})
}
}).then(res => {
file.onProgress({percent: 100})
file.onSuccess(res.data)
}).catch(erro => {
console.log(erro)
})
},
handleSuccess(response, file, fileList) {
//此处为自定义进度条的判断,不做过多说明
if (file.percentage >= 96.9) {
file.percentage = 96.9
}
let res = response.data
file.path = res.path
file.width = res.width
file.height = res.height
file.origin_name = file.name
let data = { ...this.ruleForm }
data.paths = [{ origin_name: file.name,img: res.path, height: res.height, width: res.width }]
add(data).then(response => {
file.id = response.data.id
this.materialList = fileList
this.loading = false
this.ruleForm.paths = []
this.$message({
message: response.msg,
type: 'success',
duration: 2000
});
file.percentage = 100
this.spliceUpload(file)
}).catch(res=> {
this.spliceUpload(file)
this.$message({
message: '上传失败请重新上传',
type: 'success',
duration: 2000
});
})
},
//上传成功后的操作,无论此文件添加成功或失败,uploaList都进行删除此文件
spliceUpload(file) {
this.onQueue = false
let index = this.uploadList.findIndex(item=> {
return item.file.name == file.name
})
this.uploadList.splice(index, 1)
this.uploadItems.splice(index, 1)
//删除该文件后,对应的上传文件线程-1
this.uploadLine--
},
}