在前端开发中,经常会有大批量文件上传的需求。在面对“数千张高清图片批量上传”的需求时,传统的前端上传方案往往会出现各种各样的问题:
- 一次性全部上传:极易触发服务器
413 Payload Too Large报错,且巨大的 HTTP 包体容易导致连接超时。 - 暴力循环:瞬间发起数千个 HTTP 请求,不仅会挤爆浏览器的并发限制,导致大量请求排队挂起,还可能瞬间压垮后端服务。
针对这些问题,就需要前端分批上传,下面介绍一下一种支持分组、控制并发、且具备自动重试机制的大批量文件上传策略
1. 核心设计思路
- 分批: 将 大批量文件切分成若干个小批次(比如每批 50-100 个),
- 并发控制: 一次性全部并发(太卡)。我们维护一个并发池(例如限制同时 3 个请求)。当池子满了,必须等其中一个请求结束,才能塞入下一个。这最大化利用了带宽,同时保护了浏览器和服务器。
- 失败重试: 网络是不稳定的。如果某一批次失败,不应该直接报错停止,而是应该将失败的批次收集起来,在当前轮次结束后自动重试,直到达到最大重试次数。
2. 代码实战
下面是实现该逻辑的完整代码封装。我们使用了 axios 发送请求,利用 Promise.race 实现并发控制。
1 | const handleBatchUpload = async (Files) => { |
3. 关键技术点解析
A. 使用 Promise.race 控制并发
在 for 循环中,我们不断将任务推入 pool。
pool.length === max时,意味着并发满了。await Promise.race(pool)会在池子中任意一个请求完成(resolve 或 reject)时立即解除阻塞。- 解除阻塞后,循环继续,下一个任务入池。
B. 使用递归重试
- 定义
failList收集本轮失败的批次。 - 在
finally中判断finish === list.length(本轮是否跑完)。 - 如果跑完了且
failList有数据,直接调用uploadBatches(failList, retryCount + 1)。
4.性能与稳定性分析
直觉认为:“一次性把所有文件扔给服务器最快,因为建立连接(TCP Handshake)的次数最少”。虽然分批上传增加了少量的 HTTP 握手开销(Overhead),但它有着极高的稳定性和用户体验的流畅度。并且合理的分批策略和并发控制反而比一次性上传更快。
在真实公网的环境下,我对1000张图片进行测试,进行分批上次和一次性上传时间测试,结果如下:
(1)分批上传:用时12.75s

(2)一次性上传:用时13.07s
