
在日常做后台管理、网盘系统、素材上传功能时很多前端同学都遇到过同一个头疼问题小文件上传秒成功一旦上传几十MB甚至几百MB的大文件大概率直接报错。要么接口请求超时要么网络波动导致上传失败用户只能重新上传体验极差。最开始我开发上传功能也是直接用原生 FormData 整包提交简单省事。但上线后问题频发服务器超时、请求中断、重复上传各种BUG层出不穷。后来彻底改用前端分片上传方案后大文件上传超时、断网重传、卡顿问题基本全部解决。今天我结合真实项目实战手把手带大家实现一套 JS 大文件分片上传逻辑代码可直接复用同时讲清楚原理、踩坑点和优化思路适合直接拿来做项目或者面试复盘。一、为什么大文件上传容易超时很多新手不理解为什么小文件稳得很大文件就频频翻车。其实原因很简单常规整包上传是一次性把完整文件二进制数据推给后端。目前绝大多数服务器、网关都有请求超时时间、单次请求最大体积限制。一般后端接口超时配置也就30秒、60秒一旦文件过大传输时间超过阈值网关直接主动断开连接页面直接提示超时失败。除此之外整包上传还有两个致命短板网络稍有抖动就全盘重传、无法断点续传用户体验非常糟糕。而分片上传的核心思路就是化整为零把大文件切成无数小块分批上传。二、分片上传核心原理我用通俗的话总结一下整套流程方便大家理解1. 前端获取用户上传的 File 文件对象 2. 自定义固定分片大小比如每片 5MB 3. 通过 File.slice() 方法对文件进行二进制切割 4. 循环遍历分片逐个携带分片索引、文件唯一标识并发上传 5. 后端接收所有分片并临时缓存 6. 全部分片上传完成后前端发送合并请求后端合并文件返回最终地址。这套方案最大的优势就是单次请求体积小、速度快、不会超时支持断点续传。三、前端完整实战代码可直接运行下面给大家写一套原生 JS 分片上传最简可用版本没有任何框架依赖原生代码通俗易懂可直接移植到 Vue、React 项目中。!DOCTYPE html html langzh-CN head meta charsetUTF-8 title大文件分片上传/title /head body input typefile idfileInput script // 分片大小 5MB const SLICE_SIZE 5 * 1024 * 1024; const fileInput document.getElementById(fileInput); fileInput.addEventListener(change, async function (e) { const file e.target.files[0]; if (!file) return; // 文件总片数 const totalSlice Math.ceil(file.size / SLICE_SIZE); // 文件唯一标识简易md5项目建议用md5加密文件名 const fileKey file.name file.size file.lastModified; // 循环分片上传 for (let i 0; i totalSlice; i) { // 切割分片 const start i * SLICE_SIZE; const end Math.min(start SLICE_SIZE, file.size); const sliceFile file.slice(start, end); // 组装表单数据 const formData new FormData(); formData.append(file, sliceFile); formData.append(fileKey, fileKey); formData.append(sliceIndex, i); formData.append(totalSlice, totalSlice); // 上传分片 await uploadSlice(formData); } // 所有分片上传完成请求合并文件 mergeFile(fileKey, file.name); }); // 上传单个分片 function uploadSlice(data) { return new Promise((resolve) { fetch(/api/upload/slice, { method: POST, body: data }).then(res res.json()).then(() { resolve(); }) }) } // 合并分片 function mergeFile(fileKey, fileName) { fetch(/api/upload/merge, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ fileKey, fileName }) }).then(res res.json()).then(res { console.log(上传成功, res.url); alert(文件上传完成); }) } /script /body /html以上代码是我精简后的核心版本去掉了冗余逻辑保留了最核心的分片、遍历、上传、合并流程本地部署后端接口即可直接跑通。四、解决超时的关键优化点很多同学写完分片逻辑还是会偶尔超时其实是细节没处理好我分享几个实战优化技巧。1. 合理设置分片大小分片不是越小越好也不是越大越好。太大容易超时太小请求过多挤占服务器资源。日常项目中5MB~10MB 是最稳妥的区间适配绝大多数网关超时配置。2. 增加请求间隔避免并发炸接口上面代码用的串行上传稳定性最高。如果改成并发一定要控制并发数量不然一次性几十条请求涌入容易被服务器限流反而导致上传失败。3. 增加失败重试机制网络波动很常见单个分片上传失败不需要整文件重传可以单独对失败分片重试2-3次极大提升上传成功率。五、进阶优化断点续传项目必备正式项目中一定要加上断点续传功能。原理很简单上传前先调用后端接口查询当前文件已上传的分片索引前端直接跳过已上传部分只传未完成的分片彻底解决中途暂停、刷新页面、断网重传的问题。配合文件 MD5 唯一标识校验还能实现秒传功能重复文件无需再次上传大幅提升用户体验。六、总结大文件上传超时根本问题不在于网速而在于传输方式。传统整包上传完全不适合超大文件场景只要项目涉及视频、压缩包、大素材上传分片上传几乎是行业标准方案。这套分片上传逻辑不仅能完美解决接口超时还能兼容弱网环境、支持断点续传、提升上传稳定性不管是面试作答还是项目落地都是非常实用的前端进阶技能。大家可以把本文代码敲一遍吃透分片逻辑后续开发大文件上传功能就能直接复用。