結(jié)合el-upload組件實現(xiàn)大文件分片上傳功能
前情提要
Element UI的el-upload上傳組件相信各位小伙伴都已經(jīng)非常熟悉,最近接了一個新需求,要求在el-upload組件基礎(chǔ)上實現(xiàn)分片上傳功能,即小于等于5M文件正常上傳,大于5M文件切成5M每片上傳。那么這個功能怎么實現(xiàn)呢?一起看看吧
代碼實現(xiàn)
首先,我們需要設(shè)置el-upload組件的http-request,這樣可以覆蓋默認(rèn)的上傳行為,可以自定義上傳的實現(xiàn)。
<!-- data是上傳時附帶的額外參數(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ù),file是文件 let url = "xxx" //上傳文件接口 let loadingInstance = Loading.service({ text: "正在上傳文件,請稍后...", }); 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是分片上傳方法,我們可以把它們一個單獨的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對文件進(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對象沒有定義任何方法,但它從Blob對象中繼承了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ù),file是文件 let url = "xxx" //上傳文件接口 let loadingInstance = Loading.service({ text: "正在上傳文件,請稍后...", }); 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) }) }) } // 針對單個文件進(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) }; // 針對每個文件進(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組件實現(xiàn)大文件分片上傳的文章就介紹到這了,更多相關(guān)el-upload大文件分片上傳內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue通過echarts實現(xiàn)數(shù)據(jù)圖表化顯示
Echarts,它是一個與框架無關(guān)的 JS 圖表庫,但是它基于Js,這樣很多框架都能使用它,例如Vue,估計IONIC也能用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08最全vue的vue-amap使用高德地圖插件畫多邊形范圍的示例代碼
這篇文章主要介紹了最全vue的vue-amap使用高德地圖插件畫多邊形范圍,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07解決Vue3?echarts?v-show無法重新渲染的問題
這篇文章主要介紹了Vue3?echarts?v-show無法重新渲染的問題,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09