基于Vue 和 iView分片上傳功能實現(xiàn)(上傳組件)
在實際開發(fā)中,上傳大文件往往會面臨一些問題,如上傳速度慢、超時、網(wǎng)絡(luò)中斷等。為了更好地解決這些問題,我們可以使用分片上傳技術(shù)。分片上傳就是將文件拆分成多個小塊進(jìn)行上傳,每個小塊稱為“分片”,上傳成功后,服務(wù)器會將這些分片重新合并成完整的文件。
本文將通過一個基于 Vue 和 iView 的分片上傳示例,詳細(xì)介紹如何實現(xiàn)文件分片上傳,并且為每個上傳的分片提供上傳進(jìn)度顯示和錯誤處理。
使用分片上傳技術(shù)的優(yōu)勢:
- 提高上傳成功率:即使某個分片上傳失敗,只需要重新上傳該分片,其他分片不受影響。
- 支持?jǐn)帱c續(xù)傳:分片上傳可以幫助我們實現(xiàn)斷點續(xù)傳功能。
- 支持上傳大文件:通過將大文件切分成小的分片,避免一次性上傳造成的超時問題。
前提條件
- Vue.js:用于構(gòu)建用戶界面。
- iView:一款基于 Vue 的 UI 組件庫,其中包括用于文件上傳的
Upload組件。 - Axios:用于發(fā)起 HTTP 請求,進(jìn)行文件上傳。
- 后端 API:需要提供分片上傳和文件合并接口。
1. 組件結(jié)構(gòu)
首先,使用 iView 提供的 Upload 組件來構(gòu)建文件上傳界面,界面中包含一個選擇文件按鈕和一個上傳進(jìn)度條。在 Vue 的 data 中定義上傳所需的一些變量,例如文件分片大小、上傳進(jìn)度、分片的集合等。
<template>
<div>
<!-- iView的Upload組件 -->
<Upload
:action="uploadAction"
:before-upload="beforeUpload"
:on-progress="handleProgress"
:on-success="handleSuccess"
:on-error="handleError"
:show-file-list="false"
:headers="uploadHeader"
>
<Button>選擇文件</Button>
</Upload>
<div v-if="uploading">
<Progress :percent="uploadProgress"></Progress>
</div>
</div>
</template>在上面的代碼中,使用了 iView 的 Upload 組件來處理文件選擇,Progress 組件用來展示文件上傳的進(jìn)度。before-upload 用于文件上傳前的預(yù)處理,on-progress 用來更新進(jìn)度條,on-success 和 on-error 用來處理上傳成功或失敗的回調(diào)。
2. 數(shù)據(jù)結(jié)構(gòu)
data() {
return {
uploadHeader: {
Authorization: localStorage.token, // 上傳請求的授權(quán)頭
Accept: '*/*' // 允許所有類型的響應(yīng)
},
fileName: '', // 存儲文件名
fileSize: 0, // 存儲文件大小
chunkSize: 5 * 1024 * 1024, // 每個分片的大小,這里設(shè)置為5MB
fileChunks: [], // 存儲文件的所有分片
uploading: false, // 是否正在上傳
uploadProgress: 0, // 上傳進(jìn)度
currentChunkIndex: 0, // 當(dāng)前上傳的分片索引
uploadAction: `${this.baseURL}/xxxx`, // 上傳分片的API
uploadActionMerge: `${this.baseURL}/xxx`, // 合并分片的API
};
}在 data 中,定義了上傳的必要參數(shù),包括文件名、文件大小、分片大小、上傳進(jìn)度等。uploadAction 和 uploadActionMerge 分別表示上傳分片和合并文件的 API 地址。
3. 處理文件上傳前的操作
當(dāng)文件被選中后,觸發(fā) before-upload 回調(diào)函數(shù),在該函數(shù)中我們進(jìn)行文件的驗證和分片處理。
// 上傳前的驗證和分片操作
beforeUpload (file) {
// 如果需要做格式驗證,大小檢查等,可以在這里添加驗證邏輯
this.fileName = file.name; // 記錄文件名稱
this.fileSize = file.size; // 記錄文件大小
// 調(diào)用分片處理方法
this.chunkFile(file);
return false; // 返回false表示不直接上傳,手動上傳
},4. 分片處理
chunkFile(file) {
const totalChunks = Math.ceil(file.size / this.chunkSize); // 計算分片數(shù)量
this.fileChunks = []; // 清空分片數(shù)組
// 循環(huán)切割文件為多個分片
for (let i = 0; i < totalChunks; i++) {
const start = i * this.chunkSize;
const end = Math.min(start + this.chunkSize, file.size);
const chunk = file.slice(start, end);
this.fileChunks.push(chunk); // 將當(dāng)前分片添加到分片數(shù)組
}
this.uploading = true; // 設(shè)置上傳狀態(tài)為進(jìn)行中
this.uploadNextChunk(); // 上傳第一個分片
}在 chunkFile 方法中,我們通過計算文件的總大小和每個分片的大小來確定分片數(shù)量,并將文件切割成多個分片。然后,我們將每個分片存儲在 fileChunks 數(shù)組中,并開始上傳第一個分片。
5. 上傳分片
上傳每個分片時,我們使用 FormData 來構(gòu)造上傳的表單數(shù)據(jù),并使用 axios 發(fā)送 HTTP 請求。
uploadChunk(chunk) {
const clientId = this.generateClientId(); // 生成唯一的客戶端ID
const formData = new FormData();
formData.append('file', chunk); // 添加分片
formData.append('clientId', clientId); // 客戶端ID
formData.append('chunkId', this.currentChunkIndex); // 當(dāng)前分片索引
this.axios.post(this.uploadAction, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
onUploadProgress: (event) => {
const hasUploadTotal = this.currentChunkIndex * this.chunkSize;
const percent = Math.round((hasUploadTotal + event.loaded) * 100 / this.fileSize); // 計算上傳進(jìn)度
this.uploadProgress = percent; // 更新進(jìn)度
},
}).then(res => {
if (res.data.code === 1) {
this.currentChunkIndex++; // 上傳成功,增加分片索引
this.uploadNextChunk(clientId); // 上傳下一個分片
} else {
this.$message.error('上傳失敗');
this.uploading = false;
}
}).catch(error => {
this.$message.error('上傳失敗');
this.uploading = false;
});
}6. 合并文件
當(dāng)所有分片上傳完成后,我們需要調(diào)用后端接口來合并這些分片,最終生成完整的文件。
mergeFile(clientId, fileName) {
const url = `${this.uploadActionMerge}&clientId=${clientId}&sourceName=${fileName}`;
this.axios.post(url).then(({ data }) => {
if (data.code === 1) {
this.$message.success('上傳成功');
} else {
this.$message.warning(data.message);
}
}).catch((err) => {
this.$message.error('合并文件出錯');
}).finally(() => {
// 重置狀態(tài)
this.resetUploadState();
});
}7. 生成客戶端ID
為了確保每次上傳都能被唯一標(biāo)識,我們使用當(dāng)前時間戳和隨機數(shù)生成一個客戶端ID。
generateClientId() {
const timestamp = (+new Date()).toString(32); // 時間戳轉(zhuǎn)為32進(jìn)制
let randomStr = '';
// 隨機生成字符
for (let i = 0; i < 5; i++) {
randomStr += Math.floor(Math.random() * 65535).toString(32);
}
return timestamp + randomStr; // 返回客戶端ID
}8. 上傳進(jìn)度
通過 onUploadProgress 回調(diào)函數(shù),我們可以在文件上傳過程中動態(tài)地更新進(jìn)度條,實時展示上傳進(jìn)度。
handleProgress(event) {
const hasUploadTotal = this.currentChunkIndex * this.chunkSize;
const percent = Math.round((hasUploadTotal + event.loaded) * 100 / this.fileSize); // 計算總上傳進(jìn)度
this.uploadProgress = percent; // 更新進(jìn)度條
}9. 上傳成功和失敗處理
最后,我們還可以在上傳成功或失敗時,進(jìn)行相應(yīng)的處理。
handleSuccess(response) {
this.$message.success('上傳成功');
this.uploading = false;
}
handleError(error) {
this.$message.error('上傳失敗');
this.uploading = false;
}總結(jié)
通過以上步驟,成功實現(xiàn)了基于 Vue 和 iView 組件的分片上傳功能。主要流程包括:文件選擇、文件分片、逐個分片上傳、上傳進(jìn)度顯示以及文件合并等。該方案對于大文件上傳具有較好的穩(wěn)定性和效率,尤其適用于大文件的分片上傳場景。
到此這篇關(guān)于基于Vue 和 iView分片上傳功能實現(xiàn)(上傳組件)的文章就介紹到這了,更多相關(guān)vue iview分片上傳內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+elementUI實現(xiàn)表單和圖片上傳及驗證功能示例
這篇文章主要介紹了vue+elementUI實現(xiàn)表單和圖片上傳及驗證功能,結(jié)合實例形式分析了vue+elementUI表單相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
在vue中使用回調(diào)函數(shù),this調(diào)用無效的解決
這篇文章主要介紹了在vue中使用回調(diào)函數(shù),this調(diào)用無效的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Vue3+X6流程圖實現(xiàn)數(shù)據(jù)雙向綁定詳解
這篇文章主要為大家詳細(xì)介紹了Vue3如何結(jié)合X6流程圖實現(xiàn)數(shù)據(jù)雙向綁定,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
ElementUI實現(xiàn)el-table列寬自適應(yīng)的代碼詳解
這篇文章給大家介紹了ElementUI實現(xiàn)el-table列寬自適應(yīng)的詳細(xì)步驟,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-01-01

