结合el-upload组件实现大文件分片上传功能
短信预约 -IT技能 免费直播动态提醒
前情提要
Element UI的el-upload上传组件相信各位小伙伴都已经非常熟悉,最近接了一个新需求,要求在el-upload组件基础上实现分片上传功能,即小于等于5M文件正常上传,大于5M文件切成5M每片上传。那么这个功能怎么实现呢?一起看看吧
代码实现
首先,我们需要设置el-upload组件的http-request,这样可以覆盖默认的上传行为,可以自定义上传的实现。
<!-- data是上传时附带的额外参数,uploadFile是覆盖默认上传的方法 -->
<el-upload :data="data" :http-request="uploadFile">
<el-button icon="el-icon-upload2">本地文件</el-button>
</el-upload>
接下来,uploadFile方法中需要区分文件是否超过5M
async uploadFile({ data, file }) {
// data是上传时附带的额外参数,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对文件进行切片
// 上传过程中用到的变量
const chunkSize = 5 * 1024 * 1024; // 5MB一片
const chunkCount = Math.ceil(file.size / chunkSize); // 总片数
// 获取当前chunk数据
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是上传时附带的额外参数,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); // 总片数
// 获取当前chunk数据
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)
})
})
}
// 针对单个文件进行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)
};
// 针对每个文件进行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 }
到此这篇关于结合el-upload组件实现大文件分片上传的文章就介绍到这了,更多相关el-upload大文件分片上传内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341