vue文件批量上傳及進(jìn)度條展示的實(shí)現(xiàn)方法
主要實(shí)現(xiàn)功能
1.多文件拖拽上傳
2.顯示文件上傳進(jìn)度條
3.上傳期間,還可以繼續(xù)拖拽上傳
4.可以支持手動(dòng)修改上傳并發(fā)任務(wù)數(shù)
5.上傳失敗自動(dòng)重試,最大重試次數(shù)3次
6.上傳過程中可以手動(dòng)取消上傳
本次使用的是element ui ,上傳拖拽是通過el-upload實(shí)現(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>點(diǎn)擊上傳</em> </div> <template #tip> <div class="el-upload__tip"> 請(qǐng)上傳文件,僅支持上傳文件,不支持文件夾 </div> </template> </el-upload>
上傳之前,觸發(fā) beforeUpload 方法,該方法進(jìn)行封裝調(diào)用
beforeUpload(raw) { addUploadFile(raw) return false }
上傳初始化邏輯
初始化進(jìn)度條等相關(guān)數(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 隊(duì)列,1 上傳中,2 上傳成功 , 3 取消上傳 // failTryCount 失敗上傳次數(shù), 沒上傳一次,自動(dòng)減去已,當(dāng)為0的時(shí)候,停止上傳 upload.multiFileList.push({file: raw, progress: uploadProgress, status: 0, failTryCount: 3}) multiUpload() }
該代碼引用了一個(gè)類似vuex的存儲(chǔ)庫(kù) Pinia
下面內(nèi)容通過pinia定義了一個(gè)存儲(chǔ),存儲(chǔ)有三個(gè)字段
uploadStore()
export const uploadStore = defineStore('upload', { state: () => ({ multiFileList: [], processNumber: 3, promise: [] }) })
multiUpload()
文件上傳核心內(nèi)容就是該方法了,主要時(shí)過濾上傳狀態(tài)為0,然后批量加入上傳隊(duì)列
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進(jìn)行批量上傳
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)
上傳文件邏輯,進(jìn)行文件的上傳,進(jìn)度計(jì)算等功能。本功能是模擬上傳阿里云盤操作
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 = '文件校驗(yàn)中' // ElMessage.info(fileInfo.file_name + ' 秒傳檢測(cè)中') 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
總結(jié)
到此這篇關(guān)于vue文件批量上傳及進(jìn)度條展示實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue文件批量上傳及進(jìn)度條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue代碼分割的實(shí)現(xiàn)(codesplit)
這篇文章主要介紹了vue代碼分割的實(shí)現(xiàn)(codesplit),做了代碼分割后,會(huì)將代碼分離到不同的bundle中,然后進(jìn)行按需加載這些文件,需要的朋友可以參考下2018-11-11Vue項(xiàng)目中常用的工具函數(shù)總結(jié)
這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中常用的工具函數(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-09-09使用electron打包Vue前端項(xiàng)目的詳細(xì)流程
這篇文章主要介紹了使用electron打包Vue前端項(xiàng)目的詳細(xì)流程,文中通過圖文結(jié)合的方式給大家介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)electron打包Vue有一定的幫助,需要的朋友可以參考下2024-04-04el-table 選擇框根據(jù)條件設(shè)置某項(xiàng)不可選中的操作代碼
這篇文章主要介紹了el-table 選擇框根據(jù)條件設(shè)置某項(xiàng)不可選中的操作代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-03-03vue在IIS服務(wù)器部署后路由無法跳轉(zhuǎn)
在IIS服務(wù)器上部署Vue項(xiàng)目時(shí),可能會(huì)遇到路由無法正常跳轉(zhuǎn)的問題,解決方法有兩種,下面就來具體介紹一下解決方法,感興趣的可以了解一下2024-10-10