前端使用axios实现监听上传进度
通过axios上传
axios.post('url', form, {
headers: {
'Content-Type': 'multipart/form-data',
},
onUploadProgress: (progressEvent) => {
if (progressEvent.lengthComputable) {
this.progresss = Math.round((progressEvent.loaded / progressEvent.total) * 100);
}
},
})
.then((res) => {
// TODO
});
通过ajax上传
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const progressPercentage = Math.round((event.loaded / event.total) * 100);
console.log(`上传进度: ${progressPercentage}%`);
}
});
多文件上传展示一个进度条
let progress = 0;
const UPLOAD_TYPE_MAP = {
UPLOADING: 'uploading',
COMPLATE: 'complate',
}
const files = [{ file:'', status: UPLOAD_TYPE_MAP.UPLOADING }, { file:'', status: UPLOAD_TYPE_MAP.UPLOADING }];
for (let index = 0; index < files.length; index++) {
const element = files[index];
// 1、这里是调接口的逻辑,可以是并行也可以完成一个调下一个,这个看你们的接口的限速吧,我就按照并行做了。
// 2、这里是每个文件上传完成的逻辑,更改当前文件的状态把status 改成UPLOAD_TYPE_MAP.COMPLATE
}
const timer = setInterval(() => {
const eachProgress = 100 / files.length; // 计算单个的比例
const complateUpload = files.filter((item) => item.status === UPLOAD_TYPE_MAP.COMPLATE);
const upperLimit = (complateUpload.length + 1) * eachProgress;
const maxProgress = upperLimit > 100 ? 100 : upperLimit; // 计算出当前最大进度
if(progress < maxProgress) {
progress++; // 边界控制
}
if(maxProgress === 100) {
progress = 100;
clearInterval(time);
}
}, 500);
大文件分片上传展示进度条
-
可靠性和鲁棒性:将大文件分成小块进行上传,即使出现网络中断或其他意外情况,只需要重新上传失败的分片,而不需要重新上传整个文件,提高上传的可靠性和鲁棒性。
-
传输效率:由于大文件被分成多个小块进行并行上传,可以充分利用网络带宽,提高传输速度和效率。
-
断点续传:如果上传过程中断,可以根据已成功上传的分片信息,从上次中断的地方继续上传,避免重复上传已经上传过的部分,节省时间和资源。
-
内存占用低:大文件一次性加载到内存中可能导致内存溢出,而分片上传只需加载单个分片,减少了对内存的压力,并适应内存有限的环境。
-
服务器负载平衡:使用分片上传可以将上传请求分散到多个服务器,降低单一服务器的负载压力,提高整体系统的稳定性和吞吐量。
-
灵活性:分片上传允许用户在任意时间暂停、取消或恢复上传过程,提供了更好的用户体验和操作灵活性。
// 定义分片大小(以字节为单位) // 1MB
// 将文件切割为多个分片
function sliceFileIntoChunks(file, chunkSize = 1024 * 1024) {
const fileSize = file.size;
const chunks = Math.ceil(fileSize / chunkSize);
const fileChunks = [];
let start = 0;
let end = chunkSize;
for (let i = 0; i < chunks; i++) {
const chunk = file.slice(start, end); // slice 可以把文件按照需要的大小分割
fileChunks.push(chunk);
start = end;
end = start + chunkSize;
}
return fileChunks;
}
const files = sliceFileIntoChunks(originFile).map((item) => ({file: item, status: UPLOAD_TYPE_MAP.UPLOADING}));
// ... 忽略
const timer = setInterval(() => {
const eachProgress = 100 / files.length; // 计算单个的比例
const complateUpload = files.filter((item) => item.status === UPLOAD_TYPE_MAP.COMPLATE);
const upperLimit = (complateUpload.length + 1) * eachProgress;
const maxProgress = upperLimit > 100 ? 100 : upperLimit; // 计算出当前最大进度
if(progress < maxProgress) {
progress++; // 边界控制
}
if(maxProgress === 100) {
progress = 100;
clearInterval(time);
}
}, 500);