vue 3 中显示文件上传剩余时间需用 axios 的 onuploadprogress 动态计算预估 eta:记录起始时间戳和上次 loaded,每次回调计算瞬时速度及剩余秒数并转为 mm:ss 格式,避免早期平均速度误判,推荐滑动窗口或加权平均优化精度。

在 Vue 3 中显示文件上传的剩余时间,核心是利用 axios 的 onUploadProgress 回调实时获取已上传字节数(loaded)和总字节数(total),再结合时间差动态估算速度与剩余时间。这不是直接读取“倒计时”,而是动态计算的预估剩余时间(ETA),需要手动维护时间戳和数据量。
以下为实用、可落地的关键步骤和写法:
监听上传进度并记录时间基准
在发起上传请求时,初始化两个变量:
-
起始时间戳:用
Date.now()记录开始上传的毫秒数; -
上一次已上传字节数:初始为
0,用于后续计算瞬时速度。
在 onUploadProgress 中动态计算剩余时间
每次回调触发时(浏览器高频上报),做三件事:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 算出本次与上次的时间差(秒)和数据增量(字节);
- 据此得出当前瞬时上传速度(B/s),再换算成 KB/s 或 MB/s 显示更友好;
- 用公式:
剩余时间 = (total - loaded) / 速度得到预估秒数,四舍五入后转为mm:ss格式。
注意避免常见误差点
直接用首次 loaded 和 total 算平均速度会导致早期严重不准(比如刚上传 1%,就预测要 10 分钟)。应采用“滑动窗口”式计算,例如只取最近 2–3 次回调的数据差,或加权平均。简易做法是:
- 仅在
loaded > 0 && loaded 时才更新剩余时间; - 跳过前 1–2 次回调(避免 initial burst 带来的速度虚高);
- 当速度接近 0(如网络卡顿)时,显示“计算中…”或保留上一有效值,不显示负数或 Infinity。
Vue 3 组合式写法示例(关键片段)
在 setup() 中定义响应式字段:
const leftTime = ref('—'); // 显示为 "02:15"
const speed = ref('0 KB/s');
let startTime = 0;
let lastLoaded = 0;
let lastTime = 0;
<p>const uploadFile = async () => {
const formData = new FormData();
formData.append('file', file.value);</p><p>startTime = Date.now();
lastLoaded = 0;
lastTime = startTime;</p><p>try {
await axios.post('/api/upload', formData, {
onUploadProgress: (e) => {
if (!e.lengthComputable) return;
const now = Date.now();
const deltaT = (now - lastTime) / 1000; // 秒
const deltaL = e.loaded - lastLoaded;</p><pre class="brush:php;toolbar:false;"> if (deltaT > 0.3 && deltaL > 0) { // 避免太短间隔干扰
const currentSpeed = deltaL / deltaT; // B/s
const remainBytes = e.total - e.loaded;
const remainSec = remainBytes / currentSpeed;
speed.value = formatSpeed(currentSpeed);
leftTime.value = formatTime(remainSec);
lastLoaded = e.loaded;
lastTime = now;
}
}
});} catch (err) { // 错误处理 } };
不复杂但容易忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










