問(wèn)題:項(xiàng)目基于vue開(kāi)發(fā),使用element上傳組件,該組件在文件選取后會(huì)會(huì)默認(rèn)開(kāi)始上傳,但是這樣存在一個(gè)問(wèn)題:上傳任務(wù)太多可能導(dǎo)致部分素材上傳不成功出現(xiàn)卡死的情況;服務(wù)器帶寬不夠,同時(shí)上傳速度慢,影響效率。
需求:使用隊(duì)列上傳,按需設(shè)置一次允許上傳多少文件,上傳完成一個(gè)自動(dòng)新增到隊(duì)列中,直到全部上傳完成。
隊(duì)列思想圖:

1599639274821.png
主要代碼:
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:[], //上傳隊(duì)列數(shù)組
onQueue: false, //是否在上傳
uploadItems: [], //正在上傳的數(shù)組
uploadLen: 5, //上傳文件個(gè)數(shù)限制
uploadLine: 0, //上傳文件線程
};
},
watch: {
//監(jiān)聽(tīng)上傳隊(duì)列數(shù)組是否有上傳完的,如有則觸發(fā)以下代碼
uploadList (Newfile) {
//當(dāng)onQueue為true也就是在上傳中或者uploadList文件數(shù)組上傳完為空時(shí),不繼續(xù)往下執(zhí)行
if (this.onQueue === true || Newfile.length == 0 ) return
let files = [ ...Newfile ]
//判斷上傳文件線程是否小于設(shè)置的上傳文件個(gè)數(shù)限制
if (this.uploadLine < this.uploadLen) {
let newQueueLine = this.uploadLen - this.uploadLine
//截取剩余文件放入上傳數(shù)組
let index = this.uploadLine > 0? this.uploadLen - 1 : 0
this.uploadItems = files.splice(index, newQueueLine)
this.uploadLimit(this.uploadItems)
}
},
},
methods:{
//上傳限制
uploadLimit(items) {
//遍歷文件長(zhǎng)度,就循環(huán)幾次上傳隊(duì)列函數(shù)
for (let item of items) {
this.queueUpload(item)
}
},
//上傳之前進(jìn)行判斷,如uploadList的中有該文件,則不讓添加進(jìn)去
beforeUpload(file) {
//隊(duì)列去重
if (this.uploadList.length == 0){
return true
}
for (let item of this.uploadList) {
if (item.file.name == file.name){
return false
}
}
return true
},
//將文件push進(jìn)uploadList中,此時(shí)uploadList變化,觸發(fā)watch中的監(jiān)聽(tīng)方法,開(kāi)始第一次隊(duì)列上傳
customUpload(file) {
this.uploadList.push(file)
return false
},
//隊(duì)列上傳
queueUpload(file) {
this.onQueue = true
//開(kāi)始上傳該文件后,對(duì)應(yīng)的上傳文件線程+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) {
//此處為自定義進(jìn)度條的判斷,不做過(guò)多說(shuō)明
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: '上傳失敗請(qǐng)重新上傳',
type: 'success',
duration: 2000
});
})
},
//上傳成功后的操作,無(wú)論此文件添加成功或失敗,uploaList都進(jìn)行刪除此文件
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)
//刪除該文件后,對(duì)應(yīng)的上傳文件線程-1
this.uploadLine--
},
}