vue文件批量上傳及進度條展示的實現(xiàn)方法
主要實現(xiàn)功能
1.多文件拖拽上傳
2.顯示文件上傳進度條
3.上傳期間,還可以繼續(xù)拖拽上傳
4.可以支持手動修改上傳并發(fā)任務數(shù)
5.上傳失敗自動重試,最大重試次數(shù)3次
6.上傳過程中可以手動取消上傳

本次使用的是element ui ,上傳拖拽是通過el-upload實現(xiàn)的。
<el-upload :before-upload="beforeUpload" action="#" class="upload" drag multiple > <el-icon class="el-icon--upload"> <upload-filled/> </el-icon> <div class="el-upload__text"> 拖拽或 <em>點擊上傳</em> </div> <template #tip> <div class="el-upload__tip"> 請上傳文件,僅支持上傳文件,不支持文件夾 </div> </template> </el-upload>
上傳之前,觸發(fā) beforeUpload 方法,該方法進行封裝調(diào)用
beforeUpload(raw) {
addUploadFile(raw)
return false
}上傳初始化邏輯
初始化進度條等相關數(shù)據(jù)
export function addUploadFile(raw) {
const upload = uploadStore()
const uploadProgress = {
progress: 0,
file_id: '',
file_name: raw.name,
percent: [],
speed: '0 MB',
file_size: raw.size,
upload_size: 0,
upload_time: new Date()
}
// status上傳狀態(tài) 0 隊列,1 上傳中,2 上傳成功 , 3 取消上傳
// failTryCount 失敗上傳次數(shù), 沒上傳一次,自動減去已,當為0的時候,停止上傳
upload.multiFileList.push({file: raw, progress: uploadProgress, status: 0, failTryCount: 3})
multiUpload()
}該代碼引用了一個類似vuex的存儲庫 Pinia
下面內(nèi)容通過pinia定義了一個存儲,存儲有三個字段
uploadStore()
export const uploadStore = defineStore('upload', {
state: () => ({
multiFileList: [],
processNumber: 3,
promise: []
})
})multiUpload()
文件上傳核心內(nèi)容就是該方法了,主要時過濾上傳狀態(tài)為0,然后批量加入上傳隊列
export function multiUpload() {
const upload = uploadStore()
const readFileList = []
upload.multiFileList.forEach(res => {
if (res.status === 0) {
readFileList.push(res)
}
})
if (readFileList.length > 0) {
multiRun(upload, readFileList.slice(0, upload.processNumber), uploadAsync)
}
}multiRun()
該方法,就是并發(fā)上傳核心邏輯,通過Promise進行批量上傳
function multiRun(upload, keyList, func) {
const processNumber = upload.processNumber
const promise = upload.promise
for (let i = 0; i < processNumber - promise.length; i++) {
promise.push(Promise.resolve())
}
let reduceNumber = promise.length - processNumber
if (reduceNumber > 0) {
upload.promise = promise.slice(0, reduceNumber)
}
for (let j = 0; j < keyList.length; j += processNumber) {
for (let i = 0; i < processNumber; i++) {
if (i + j < keyList.length) {
promise[(j + i) % processNumber] = promise[(j + i) % processNumber].then(() => func(keyList[i + j])).catch(({
fileInfo,
err
}) => {
if (fileInfo.status === 3) {
console.log(fileInfo.file.name, '取消上傳')
} else {
fileInfo.status = 0
fileInfo.failTryCount -= 1
if (fileInfo.failTryCount < 1) {
ElMessage.error(`${fileInfo.file.name} 超過最大重試次數(shù),停止上傳`)
} else {
ElMessage.error(`${fileInfo.file.name} 上傳失敗,正在重試`)
console.log(fileInfo.file.name, err)
multiUpload()
}
}
})
}
}
}
}uploadAsync(fileInfo)
上傳文件邏輯,進行文件的上傳,進度計算等功能。本功能是模擬上傳阿里云盤操作
function uploadAsync(fileInfo) {
const progress = fileInfo.progress
const file = fileInfo.file
return new Promise((resolve, reject) => {
progress.file_name = file.name
progress.file_size = file.size
if (fileInfo.status === 0) {
fileInfo.status = 1
} else {
return resolve()
}
progress.progress = 10
getUploadSid().then(async res => {
// ElMessage.info(fileName + ' 文件讀取中')
progress.speed = '文件讀取中'
let hash = await PreHash(file, progress)
let fileHashInfo = {
sid: res.data.sid,
file_name: progress.file_name,
file_size: progress.file_size,
pre_hash: hash
}
progress.progress = 20
checkPreHash(fileHashInfo).then(async pRes => {
if (pRes.data.check_status === true) {
// 秒傳邏輯
progress.progress = 30
const md5Code = pRes.data.md5_token
progress.speed = '文件校驗中'
// ElMessage.info(fileInfo.file_name + ' 秒傳檢測中')
let hash = await ContentHash(file, md5Code, progress)
fileHashInfo.proof_code = hash.proofCode
fileHashInfo.content_hash = hash.conHash
checkContentHash(fileHashInfo).then(async cRes => {
if (cRes.data.check_status === true) {
progress.progress = 100
progress.upload_size = progress.file_size
progress.speed = '秒傳成功'
// ElMessage.success(fileName + ' 上傳成功')
fileInfo.status = 2
fileInfo.upload_time = new Date()
multiUpload()
resolve()
} else {
return await ChunkedUpload(fileInfo, fileHashInfo, cRes.data.upload_extra, cRes.data.part_info_list, () => {
fileInfo.status = 2
fileInfo.upload_time = new Date()
multiUpload()
resolve()
}, (err) => {
reject({fileInfo, err})
})
}
}).catch((err) => {
reject({fileInfo, err})
})
} else {
return await ChunkedUpload(fileInfo, fileHashInfo, pRes.data.upload_extra, pRes.data.part_info_list, () => {
fileInfo.status = 2
fileInfo.upload_time = new Date()
multiUpload()
resolve()
}, (err) => {
reject({fileInfo, err})
})
}
}).catch((err) => {
reject({fileInfo, err})
})
}).catch((err) => {
reject({fileInfo, err})
})
})
}核心上傳大概就是這些邏輯
代碼源碼:xshare/upload.js at main · nineaiyu/xshare · GitHub
總結
到此這篇關于vue文件批量上傳及進度條展示實現(xiàn)的文章就介紹到這了,更多相關vue文件批量上傳及進度條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
el-table 選擇框根據(jù)條件設置某項不可選中的操作代碼
這篇文章主要介紹了el-table 選擇框根據(jù)條件設置某項不可選中的操作代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-03-03

