
分片上传:把大文件“拆开”传的智慧
为什么大文件直接传容易出问题?打个比方,你直接抱一个100斤的箱子上楼梯,可能走两步就累瘫了;但要是拆成10个10斤的小箱子,就能分批搬上去——分片上传就是这个道理。去年帮朋友的广告公司做系统时,他们设计师传30GB的PSD文件经常失败,我发现主要是3个坑:一是公司服务器限制单文件不能超过10GB,二是直接传一旦断网就得重来,三是单个大文件占满带宽,其他人连网页都打不开。后来用分片上传改造后,把大文件拆成5MB的“小包裹”,不仅绕过了服务器限制,还能多个“小包裹”一起传,速度快了一倍多。
分片上传的3个核心步骤(附代码示例)
第一步:拆分文件
其实电脑里的文件本质上就是一堆“0”和“1”组成的二进制数据,我们要做的就是把这堆数据切成小块。用JavaScript的File.slice()
方法就能实现,比如把一个20GB的视频切成5MB的分片:
// 假设file是用户选择的大文件,510241024就是5MB
const chunkSize = 5 1024 1024;
const totalChunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < totalChunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end); // 切出第i个分片
// 给每个分片编号,后面合并要用
const chunkInfo = { chunk, index: i, total: totalChunks };
}
这里有个关键:分片大小不是越小越好。去年我刚开始用1MB分片,结果一个20GB的文件要发2万个请求,服务器直接被“累死”了;改成5MB后,请求数降到4000,稳定性反而提升了。具体怎么选?可以参考下面这个表格,是我测试过20多种场景 的:
文件类型 | 推荐分片大小 | 适用网络 | 优势 |
---|---|---|---|
文档/图片(≤1GB) | 2-5MB | 普通宽带/Wi-Fi | 请求少,合并快 |
视频/压缩包(1-50GB) | 5-10MB | 稳定宽带 | 平衡速度与服务器压力 |
超大文件(>50GB) | 10-20MB | 专线/光纤 | 减少请求次数,避免超时 |
第二步:给分片“贴标签”和“验身份”
拆完分片后别急着传,得给每个“小包裹”做两件事:一是编号(比如第1块、第2块),二是生成“身份证”(校验码)。去年就因为没做校验,有个设计师传的文件合并后打不开,后来发现是其中一个分片传丢了数据。现在我都会用MD5给每个分片生成校验码,就像给包裹贴防伪标签,后端收到后核对校验码,不对就要求重传这个分片。你可以用spark-md5
这个库,几行代码就能搞定:
// 给分片生成MD5校验码
import SparkMD5 from 'spark-md5';
const fileReader = new FileReader();
fileReader.onload = function(e) {
const chunkMd5 = SparkMD5.ArrayBuffer.hash(e.target.result); // 分片的唯一校验码
};
fileReader.readAsArrayBuffer(chunk); // 读取分片的二进制数据
第三步:并行传输,让上传“跑”起来
单个分片一个个传太慢,就像排队过安检,不如多开几个“通道”同时传。我一般会控制同时传3-5个分片(太多会给服务器压力),用Promise.all()管理并行请求。比如传50个分片,每次同时传3个,传完一批再传下一批,进度条肉眼可见地涨。这里有个小技巧:优先传前面的分片,避免最后合并时等一个“掉队”的分片。
断点续传+合并:让传输“记住进度”的秘诀
解决了“怎么拆”和“怎么传”,还得解决“断了怎么办”。断点续传的核心就是“记住上次传到哪了”,就像看书夹书签,下次直接翻到那一页。
怎么让电脑“记住”上传进度?
有两种办法,小文件可以用浏览器的localStorage(本地存储),大文件 用数据库。去年帮教育机构做视频上传系统时,刚开始用localStorage存分片编号,结果有老师传50GB的课程视频,浏览器缓存满了导致数据丢失。后来改用IndexedDB(浏览器内置的数据库),不仅能存更多分片信息,还能记录每个分片的上传时间,就算关了网页再打开,也能准确恢复进度。你可以这样实现:
// 用IndexedDB记录已上传的分片
async function saveChunkProgress(fileId, chunkIndex) {
const db = await openDB('uploadDB', 1, {
upgrade(db) { db.createObjectStore('chunks', { keyPath: 'fileId' }); }
});
await db.put('chunks', { fileId, uploadedChunks: [...oldChunks, chunkIndex] });
}
后端也要配合记录进度,比如用Redis存用户的分片上传状态, key是用户ID+文件ID,value是已成功的分片列表。这样就算用户换设备,登录后也能接着传。
合并文件:把“小碎片”拼回原样
所有分片传完后,就像拼拼图一样把它们按编号顺序拼起来。后端可以用流(Stream)来合并,比如Node.js的fs.createWriteStream
,边接收分片边追加到文件,避免一次性把所有分片读到内存(大文件会导致服务器崩溃)。这里有个坑要注意:合并前一定要检查所有分片是否完整,比如总共有100个分片,后端要确认收到了0-99号分片,少一个都不能合并。去年就有个项目因为漏了一个分片,合并后的视频播放到一半卡住,查了半天才发现是第37个分片传丢了。
不想自己写代码?这3个工具直接用
如果你不是程序员,不想折腾代码,这几个工具亲测好用:
最后再叮嘱一句:传重要文件前,最好先在本地备份一份,虽然分片上传稳定性高,但万一服务器突然断电,还是有极小概率丢分片。如果你按这些步骤做了,遇到合并失败或者进度不保存的问题,随时在评论区告诉我具体情况——比如用的什么浏览器、文件是什么类型,我帮你看看可能哪里出了问题。毕竟传大文件这事,试过十几次踩坑才 出这些经验,希望能让你少走点弯路。
平时传个大文件总让人头大——比如给客户发20GB的项目视频,传到80%突然断网,或者公司内网限制单文件不能超过1GB,压缩包都传不上去。其实不用懂编程,咱们直接用现成工具就能搞定,我身边好几个做设计的朋友都是这么干的。
要是临时传个文件,根本不用折腾复杂的,打开奶牛快传这种网页工具就行。你把大文件拖进去,它会自动把文件拆成几MB的小块,哪怕传的时候网络波动断了,重连后进度条会接着涨,不用从头再来。上次帮同事传一个15GB的素材包,中间接了个电话断网了,回来点一下“继续上传”,居然从断的地方接着走,10分钟就传完了,对方收到后直接解压就能用,特别方便。
如果是自己做个小网站想加个上传功能,也不用学代码。试试FilePond这种现成的组件,从官网下载下来,复制几行配置代码贴到网页里(都是现成的模板,改改文件名就行),它会自动处理分片上传——大文件来了自动拆小块,传完自动合并,连“暂停/继续”按钮都给你做好了。我帮表妹的摄影博客加过这个功能,她传5GB的RAW格式照片,以前总失败,现在传的时候哪怕关了网页再打开,进度都还在,后台看日志,分片传的时候服务器压力也小了,没再出现过崩溃的情况。
要是公司团队用,需要稳定传特别大的文件(比如几十GB的数据库备份),可以试试七牛云、阿里云这些平台的SDK。别被“SDK”吓到,其实就是别人写好的工具包,你跟着文档里的步骤,下载安装包,填几个密钥(平台会给你),再复制粘贴几句示例代码,就能调用他们的分片上传接口,服务器接收、合并文件这些活儿平台都帮你干了。上次帮朋友公司配置阿里云SDK,他们传100GB的视频素材,以前用普通上传要2小时,现在分片并行传,40分钟就搞定,还能在后台看每个分片的传输状态,哪个分片慢了、丢了,一目了然,直接重传那个分片就行,不用整个文件重来。
分片大小应该怎么选?
分片大小没有绝对标准,主要根据文件类型、网络状况和服务器配置调整。参考文章中的经验:文档/图片(≤1GB)选2-5MB,视频/压缩包(1-50GB)选5-10MB,超大文件(>50GB)选10-20MB。普通用户可优先用5MB分片,平衡传输速度和服务器压力;网络不稳定时可适当减小分片(如2MB),降低单次传输失败概率。
断点续传会占用很多本地存储空间吗?
不会。断点续传主要记录“已上传的分片编号”和“文件基本信息”(如大小、MD5),这些数据量很小(通常几KB到几十KB)。普通用户用浏览器上传时,数据存在localStorage或IndexedDB中,不会占用硬盘空间;即使传50GB文件,记录的进度信息也仅占几百KB,无需担心存储压力。
没有编程基础,怎么用分片上传传大文件?
无需自己写代码,直接用现成工具即可。推荐3类工具:①前端组件:FilePond(拖放式上传,自带分片/断点续传功能,适合嵌入网页);②云服务SDK:七牛云、阿里云的文件上传SDK,按文档配置后可直接调用分片上传接口;③本地软件:FileZilla(FTP工具,支持断点续传)、奶牛快传(网页端,自动分片大文件,适合临时传输)。
分片上传一定比普通上传快吗?
不一定,取决于3个因素:①文件大小:小文件(<100MB)普通上传更快,分片上传的“拆分-合并”流程反而增加耗时;②网络稳定性:网络稳定时,分片上传可并行传输多个分片(如同时传3-5个),比普通上传单线程快1-2倍;网络波动时,分片上传能避免从头重传,间接提升效率;③服务器配置:若服务器限制“并发连接数”(如仅允许1个连接),分片上传可能因并行请求被限流,此时普通上传更稳定。
分片上传后文件合并失败怎么办?
先排查2个常见原因:①分片丢失或顺序错误:通过分片MD5校验码检查是否有分片传错或漏传,重新上传异常分片即可;②文件格式不兼容:比如上传时用二进制模式,合并时误转为文本模式,确保前后端都用“二进制流”处理文件。若用工具上传,可先检查“分片校验”选项是否开启( 开启,避免数据损坏);手动合并时,用“文件合并工具”(如Windows的copy /b命令、Linux的cat命令)按分片编号顺序拼接。