当前位置: 首页 > 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 值,供下一次回调使用。

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

http://www.dtcms.com/a/184858.html

相关文章:

  • 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 的区别
  • 轻量服务器与宝塔
  • 查看YOLO版本的三种方法
  • Rockchip RK3308 开发(二)
  • Ingrees 控制器与 Ingress 资源的区别
  • 移动应用开发的六大设计原则
  • Pygame游戏之躲避游戏
  • Vivado中可新建的工程类型解析
  • Linux基础(查找/打包/压缩文件)
  • 显存优化:梯度检查点Gradient Checkpoint和梯度累积Gradient Accumulation
  • 【嵌入式DIY实例-Arduino篇】-DIY遥控手柄