結(jié)合el-upload組件實(shí)現(xiàn)大文件分片上傳功能
前情提要
Element UI的el-upload上傳組件相信各位小伙伴都已經(jīng)非常熟悉,最近接了一個(gè)新需求,要求在el-upload組件基礎(chǔ)上實(shí)現(xiàn)分片上傳功能,即小于等于5M文件正常上傳,大于5M文件切成5M每片上傳。那么這個(gè)功能怎么實(shí)現(xiàn)呢?一起看看吧
代碼實(shí)現(xiàn)
首先,我們需要設(shè)置el-upload組件的http-request,這樣可以覆蓋默認(rèn)的上傳行為,可以自定義上傳的實(shí)現(xiàn)。
<!-- data是上傳時(shí)附帶的額外參數(shù),uploadFile是覆蓋默認(rèn)上傳的方法 --> <el-upload :data="data" :http-request="uploadFile"> <el-button icon="el-icon-upload2">本地文件</el-button> </el-upload>
接下來,uploadFile方法中需要區(qū)分文件是否超過5M
async uploadFile({ data, file }) { // data是上傳時(shí)附帶的額外參數(shù),file是文件 let url = "xxx" //上傳文件接口 let loadingInstance = Loading.service({ text: "正在上傳文件,請(qǐng)稍后...", }); try { // 如果文件小于5MB,直接上傳 if (file.size < 5 * 1024 * 1024) { let formData = new FormData(); for (let key in data) { formData.append(key, data[key]); } formData.append("file", file); const res = await upload(url,formData); loadingInstance.close(); return res; } else { // 如果文件大于等于5MB,分片上傳 data.file = file; const res = await uploadByPieces(url,data); loadingInstance.close(); return res; } } catch (e) { loadingInstance.close(); return e; } }
upload方法就是正常上傳方法,uploadByPieces是分片上傳方法,我們可以把它們一個(gè)單獨(dú)的js文件中,方便我們使用。
upload方法:
const upload = (url, data, headers = {}) => { return new Promise((resolve, reject) => { axios({ url, method: "post", data, headers: { ...headers, 'Content-Type': 'multipart/form-data' } }).then(res => { return resolve(res.data) }).catch(err => { return reject(err) }) }) }
在uploadByPieces方法中我們可以使用file.slice對(duì)文件進(jìn)行切片
// 上傳過程中用到的變量 const chunkSize = 5 * 1024 * 1024; // 5MB一片 const chunkCount = Math.ceil(file.size / chunkSize); // 總片數(shù) // 獲取當(dāng)前chunk數(shù)據(jù) const getChunkInfo = (file, index) => { let start = index * chunkSize; let end = Math.min(file.size, start + chunkSize); let chunk = file.slice(start, end); return { start, end, chunk }; };
File對(duì)象沒有定義任何方法,但它從Blob對(duì)象中繼承了slice方法:MDN
完整代碼
upload.vue
<template> <el-upload :data="data" :http-request="uploadFile"> <el-button icon="el-icon-upload2">文件上傳</el-button> </el-upload> </template> <script> // 引入上傳文件方法 import { upload, uploadByPieces } from "@/utils/upload.js"; // Loading import { Loading } from "element-ui"; export default { props: ["data"], methods: { async uploadFile({ data, file }) { // data是上傳時(shí)附帶的額外參數(shù),file是文件 let url = "xxx" //上傳文件接口 let loadingInstance = Loading.service({ text: "正在上傳文件,請(qǐng)稍后...", }); try { // 如果文件小于5MB,直接上傳 if (file.size < 5 * 1024 * 1024) { let formData = new FormData(); for (let key in data) { formData.append(key, data[key]); } formData.append("file", file); const res = await upload(url,formData); loadingInstance.close(); return res; } else { // 如果文件大于等于5MB,分片上傳 data.file = file; const res = await uploadByPieces(url,data); loadingInstance.close(); return res; } } catch (e) { loadingInstance.close(); return e; } } } } </script>
upload.js
import axios from "axios"; //正常上傳 const upload = (url, data, headers = {}) => { return new Promise((resolve, reject) => { axios({ url, method: "post", data, headers: { ...headers, 'Content-Type': 'multipart/form-data' } }).then(res => { return resolve(res.data) }).catch(err => { return reject(err) }) }) } //分片上傳 const uploadByPieces = async (url,{ fileName, file }) => { // 上傳過程中用到的變量 const chunkSize = 5 * 1024 * 1024; // 5MB一片 const chunkCount = Math.ceil(file.size / chunkSize); // 總片數(shù) // 獲取當(dāng)前chunk數(shù)據(jù) const getChunkInfo = (file, index) => { let start = index * chunkSize; let end = Math.min(file.size, start + chunkSize); let chunk = file.slice(start, end); return { start, end, chunk }; }; // 分片上傳接口 const uploadChunk = (data) => { return new Promise((resolve, reject) => { axios({ url, method: "post", data, headers: { 'Content-Type': 'multipart/form-data' } }).then(res => { return resolve(res.data) }).catch(err => { return reject(err) }) }) } // 針對(duì)單個(gè)文件進(jìn)行chunk上傳 const readChunk = (index) => { const { chunk } = getChunkInfo(file, index); let fetchForm = new FormData(); fetchForm.append("chunk", chunk); fetchForm.append("index", index); fetchForm.append("chunkCount", chunkCount); return uploadChunk(fetchForm) }; // 針對(duì)每個(gè)文件進(jìn)行chunk處理 const promiseList = [] try { for (let index = 0; index < chunkCount; ++index) { promiseList.push(readChunk(index)) } const res = await Promise.all(promiseList) return res }catch (e) { return e } } export { upload, uploadByPieces }
到此這篇關(guān)于結(jié)合el-upload組件實(shí)現(xiàn)大文件分片上傳的文章就介紹到這了,更多相關(guān)el-upload大文件分片上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3錨點(diǎn)定位兩種實(shí)現(xiàn)方式示例
這篇文章主要給大家介紹了關(guān)于vue3錨點(diǎn)定位兩種實(shí)現(xiàn)的相關(guān)資料,說到錨點(diǎn)定位,很多人第一時(shí)間會(huì)想到 a標(biāo)簽,但是a標(biāo)簽實(shí)現(xiàn)的錨點(diǎn)定位并不是那么的完美,需要的朋友可以參考下2023-07-07Vue通過echarts實(shí)現(xiàn)數(shù)據(jù)圖表化顯示
Echarts,它是一個(gè)與框架無關(guān)的 JS 圖表庫(kù),但是它基于Js,這樣很多框架都能使用它,例如Vue,估計(jì)IONIC也能用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08vue后臺(tái)管理之動(dòng)態(tài)加載路由的方法
這篇文章主要介紹了vue后臺(tái)管理之動(dòng)態(tài)加載路由的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08最全vue的vue-amap使用高德地圖插件畫多邊形范圍的示例代碼
這篇文章主要介紹了最全vue的vue-amap使用高德地圖插件畫多邊形范圍,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07vue實(shí)現(xiàn)多個(gè)數(shù)組合并
這篇文章主要介紹了vue實(shí)現(xiàn)多個(gè)數(shù)組合并方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06解決Vue3?echarts?v-show無法重新渲染的問題
這篇文章主要介紹了Vue3?echarts?v-show無法重新渲染的問題,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09