当前位置: 首页 > news >正文

文件(分片)并行上传时计算总的上传进度

1. 基于已上传字节数计算

<template><input type="file" multiple @change="uploadFiles" /><div>总进度:{{ totalProgress }}%</div>
</template><script>
export default {data() {return {totalProgress: 0,filesProgress: {}, // 存储每个文件的上传进度 { filename: percentage }}},methods: {async uploadFiles(e) {const files = e.target.files;if (!files.length) return;// 初始化进度记录this.filesProgress = {};Array.from(files).forEach(file => {this.filesProgress[file.name] = 0;});// 并行上传const promises = Array.from(files).map(file => {const formData = new FormData();formData.append('files', file);return axios.post('/upload', formData, {onUploadProgress: (progressEvent) => {// 更新单个文件进度this.filesProgress[file.name] = Math.round((progressEvent.loaded / progressEvent.total) * 100);// 计算总进度this.calculateTotalProgress();}});});await Promise.all(promises);},calculateTotalProgress() {const progresses = Object.values(this.filesProgress);const total = progresses.reduce((sum, p) => sum + p, 0);this.totalProgress = Math.round(total / progresses.length);}}
}
</script>

原理:
为每个文件维护独立的进度(0-100)
实时计算所有文件进度的平均值

2. 基于已上传文件数计算(适合等大小文件)

data() {return {uploadedCount: 0,totalFiles: 0}
},
methods: {async uploadFiles(e) {const files = e.target.files;this.totalFiles = files.length;this.uploadedCount = 0;await Promise.all(files.map(file => {return axios.post('/upload', file).then(() => {this.uploadedCount++;this.totalProgress = Math.round((this.uploadedCount / this.totalFiles) * 100);});}));}
}

适用场景:当所有文件大小相近时更高效,实际计算的上传文件数占总数的比

3. 精确字节级计算

data() {return {totalSize: 0,       总字节数prevLoadedMap: {}, // 存储 { 文件名: 上次loaded值 }uploadedSize: 0,   // 总已上传字节数}
},
methods: {
getPrevLoaded(filename) {return this.prevLoadedMap[filename] || 0;},savePrevLoaded(filename, loaded) {this.prevLoadedMap[filename] = loaded;},async uploadFiles(e) {const files = e.target.files;// 计算总大小this.totalSize = Array.from(files).reduce((sum, file) => sum + file.size, 0);this.uploadedSize = 0;const promises = files.map(file => {const formData = new FormData();formData.append('file', file);return axios.post('/upload', formData, {onUploadProgress: (progressEvent) => {// 累加已上传字节数this.uploadedSize += progressEvent.loaded - this.getPrevLoaded(file.name);this.savePrevLoaded(file.name, progressEvent.loaded);this.totalProgress = Math.round((this.uploadedSize / this.totalSize) * 100);}});});await Promise.all(promises);}
}
  1. progressEvent.loaded 的特性
    progressEvent.loaded 表示 当前文件已上传的字节数。
    在文件上传过程中,这个值会通过多次回调递增(例如从 0 → 500KB → 1MB → 完整文件大小)。
    问题:如果直接累加 progressEvent.loaded,会导致重复计算(例如第一次+500KB,第二次+1MB,实际只新增了500KB,但会错误累加1MB)。
  2. 解决重复累加的关键
    this.getPrevLoaded(file.name)
    获取该文件上一次回调时的 loaded 值(初始为0)。
    progressEvent.loaded - this.getPrevLoaded(file.name)
    计算出本次回调新增的字节数(正确的增量)。
    this.savePrevLoaded(file.name, progressEvent.loaded)
    保存当前 loaded 值,供下一次回调使用。

需要记录每个文件上次已上传的字节数
适用于文件大小差异大的场景

相关文章:

  • Linux基础开发工具一(yum/apt ,vim)
  • C++内存管理详解
  • ES 面试题系列「二」
  • HTML难点小记:一些简单标签的使用逻辑和实用化
  • 49.EFT测试与静电测试环境和干扰特征分析
  • RS485和RS232 通信配置
  • 【Linux高级全栈开发】2.1高性能网络-网络编程——2.1.1 网络IO与IO多路复用——select/poll/epoll
  • Kubernetes排错(十四):Pod状态异常排查手册
  • 每日脚本 5.11 - 进制转换和ascii字符
  • Lambda表达式能用在哪些场景?
  • libcurl简单使用
  • TeledyneLeCroy在OFC2025 EA展台上展示了其400G/800G的全包围的测试解决方案,满足了UEC联盟和UALINK联盟的技术需求
  • [Java][Leetcode simple]26. 删除有序数组中的重复项
  • 欧拉路与欧拉回路(模板)
  • Java学习笔记(对象)
  • 图形硬件系统
  • FPGA生成随机数的方法
  • InnoDB引擎
  • 红外遥控键
  • RDD转换操作中的 关于数据分区coalesce 和 repartition 的区别
  • 融创中国:境外债务重组计划聆讯定于9月15日召开
  • SIFF动画单元公布首批片单:《燃比娃》《凡尔赛玫瑰》等
  • 图讯丨习近平出席中国-拉美和加勒比国家共同体论坛第四届部长级会议开幕式
  • 新闻1+1丨婚姻登记服务,如何跑出幸福加速度?
  • 上海建筑领域绿色发展2025年工作要点发布
  • 来伊份深夜回应“粽子中吃出疑似创可贴”:拿到实物后会查明原因