文件分割 使用 Web Worker 分割 使用拥塞算法决定分割尺寸 网络最大请求数为6,使用数组设置最大请求数,promise.all 在网络环境不佳的情况下,分片上传尤为有利。如果上传过程中出现失败,您只需重传失败的部分,避免重新上传整个文件的麻烦,节省了时间和带宽。 网络状态不好时,分片尺寸应该小一点,这样可以减少单片上传过程中出现失败的机率,避免重新上传 弱网环境下需要更小的分片来减少失败率,而高速网络可以使用较大的分片以提高效率。 获取网络速度:
- 计算最新一片上传的耗时 navigator.connection { downlink: 10, effectiveType: "4g", onchange: null, rtt: 50, saveData: false, type: "wifi" //台式机不带无线网卡可能不存在该属性} 其中包含了以下几个属性: downlink:以兆比特每秒(Mbps)计的下行速度,即从服务器下载数据的速率。 downlinkMax:网络基础设施允许的最大下行速度。 effectiveType:可用连接的最佳层面的字符串。可能的值包括:slow-2g、2g、3g、4g。 rtt:往返时间(ms),从设备到服务器和返回的时间。 type:表示当前设备的网络类型。可能的值包括:bluetooth、cellular、ethernet、none、mixed、other、unknown、wifi。 saveData:表示设备是否正在使用网络代理来保存数据。默认为 false。 慢启动上传策略 这里我们简单提一下:TCP 的慢启动策略是为了解决网络拥塞导致的网络传输效率减低,丢包发生后的解决办法 。本文的大文件慢启动策略是为了解决 上行带宽跑不满/太小造成的资源浪费 的问题 以及再网络波动的场景下如何保证传输效率的问题。下图是 TCP 的慢启动策略: 慢开始,快恢复 加法增大,乘法减小
补充
补充:大文件上传的关键是「分片 + 并发 + 断点续传 + 秒传」,配合 Web Worker 与网络状况自适应可以兼顾稳定性与吞吐。
典型流程:
- 客户端:用
File.slice把文件切成 N 片(5MB 左右),计算每片 hash(可用 Web Worker + SparkMDash / SubtleCrypto 异步计算)。 - 秒传校验:把整个文件的 hash 发到服务端,服务端判断是否已存在,存在则直接返回成功。
- 分片上传:用
Promise.all控制并发(如 6 路),失败分片单独重试,配合AbortController可取消。 - 服务端合并:所有分片上传成功后,服务端按序号合并成完整文件,存储到对象存储 / OSS。
// 简化示例
async function upload(file) {
const chunkSize = 5 * 1024 * 1024;
const chunks = [];
for (let i = 0; i < file.size; i += chunkSize) {
chunks.push(file.slice(i, i + chunkSize));
}
const tasks = chunks.map((chunk, idx) => () =>
fetch('/upload', { method: 'POST', body: chunk, headers: { 'X-Index': idx } })
);
await runConcurrent(tasks, 6); // 自定义并发控制
}
补充:网络自适应切片
- 通过
navigator.connection.downlink / rtt判断当前网络状况,动态调整切片大小:弱网用 1-2MB,强网用 10MB+。 - 通过最近一次分片上传耗时动态反馈,丢包率高时缩小切片、提高并发重试次数。
补充:推荐使用成熟的库(如
uppy、tus-js-client、webuploader),它们已经封装了分片、并发、重试、续传等逻辑。



