资讯动态

WebUploader+PHP实现大文件分片上传与断点续传完整指南

发布时间:2026/10/18 4:18:12 来源:尧图企业网站定制
前段时间接了个内部项目要支持用户批量上传几百MB甚至上GB的教学视频到服务器做归档。一开始图省事前端直接用普通文件选择框后端PHP拿$_FILES接住就完了。结果测试的时候网络稍微一波动整个上传就失败重新传又得从零开始用户骂声一片。后来老老实实换成了分片上传配合断点续传才算把这个事彻底解决。这次就把WebUploader和PHP配合实现大文件分片上传的完整方案整理出来里面包含了踩坑记录和一些关键细节的取舍给正在做类似功能的后端或者全栈朋友做个参考。这个方案适合什么场景呢你的项目里如果涉及视频、安装包、日志备份这些动不动就上百MB的文件或者用户的网络环境不稳定比如内部专线带宽不高、移动网络切换频繁那这套方案基本能帮你把“上传失败重来”的恶性循环打断。核心价值就三个把大文件切碎逐个传、记住进度只补没传的数据、传完自动拼回原文件。下面从思路到代码一步一步拆开讲。1. 整体设计分片上传怎么解决“大文件传不动”的问题1.1 为什么选WebUploader而不是别的组件提到大文件上传业界方案不少比如 Plupload、Resumable.js、还有各种基于 XMLHttpRequest 自己封装的上传逻辑。我最终选 WebUploader原因很实际它虽然已经停止维护了但百度开源出来的这个项目在“分片上传”这个垂直场景上做得相当成熟API设计直白中文文档完整网上案例多到搜都搜不完真要出问题踩坑资料比冷门库好找得多。WebUploader 默认就支持分片chunked: true自带并发控制、进度回调、文件队列管理这些能力如果从零手写至少要花两三天的功夫。手写 XMLHttpRequest 分片上传也不是不行但你要自己维护每个分片的发送状态、重试逻辑、并发控制工作量和要踩的坑呈指数上升。选 WebUploader 属于“花最小的代价解决最疼的问题”。1.2 整体流程与角色分工分片上传这个方案模式上像搬家工人搬大件家具。整件沙发搬不动也搬不进电梯就把它拆成几个部件分批搬上去到了房间再拼装还原。网络传输也一样一个1GB的文件整体走HTTP上传哪怕带宽再宽中途任意一秒断掉前面传的数据全部作废。切成几MB一块的小分片后每片独立传输哪一片失败了就重传哪一片其他已上传的分片不受影响。具体到落地整个流程是这样分工的浏览器端WebUploader负责把文件切成固定大小的分片给每个分片编号把文件内容的唯一标识通常是md5连同分片序号一起发给后端展示上传进度。后端PHP负责接收每个分片把分片按“文件标识分片序号”命名保存到临时目录记录整个文件的接收进度所有分片到齐后按序号拼回完整文件。前端和后端的配合有点像工单系统前端拿着文件指纹md5去后端查“这个活干到哪了”后端返回一个已接收分片序号列表前端直接跳过这些分片从没传的继续传。这就是断点续传能成立的根基。1.3 分片大小的权衡不是越大越好也不是越小越好分片大小是个很有讲究的参数。WebUploader 里用chunkSize控制我项目里最终定的是2MB。为什么不是10MB或者1MB这里有个权衡分片太大单个分片传输时间久中途断网的概率和损失都在上升。比如网络不稳定时10MB的分片传到一半断了重传这10MB的成本比2MB大得多。分片太小虽然单次失败损失小但分片数量激增。1GB文件切2MB就是512片如果切512KB就是2048片每片都是一次HTTP请求请求往返的开销网络延迟、服务端IO、PHP进程处理会显著拉低整体速度。还有并发因素WebUploader 默认有threads并发数我设的是3。如果分片太碎同时并发几十个后端磁盘IO和PHP进程都会被拖垮。实测下来2MB到5MB是体验比较平衡的区间。如果服务器磁盘性能一般建议往2MB靠如果内网传输速度快、带宽充裕可以放宽到5MB。2. 核心原理拆解断点续传背后的“记忆能力”2.1 分片是怎么解决上传失败的普通上传是一竿子买卖文件内容从请求开始写到请求结束中间不能断断了就得重新来。分片上传把这一竿子买卖拆成多个独立小买卖每个分片都是一个完整的HTTP请求可以并行也可以排队服务端各自独立处理。这里面有个容易被忽略的点分片虽然拆开了但它们之间存在“顺序语义”。服务端保存分片时绝对不能依赖文件名自然排序必须显式保存“这是第几个分片”的索引。WebUploader 默认会在请求参数里带上chunk当前分片序号和chunks总分片数后端必须保存这两个字段合并的时候按chunk从小到大拼装。我在解析参数时就遇到过chunk被当成字符串导致顺序错乱的坑后面会细说。分片解决失败的另一个关键机制是“独立重试”。WebUploader 发送某个分片失败后会自动重试这个分片retry接口不会影响其他分片的发送。用户全程无感只是进度条停了一下又继续往前跳。2.2 断点续传的记忆机制用md5当文件的“身份证”断点续传的核心不是断点时刻发生了什么而是重传时怎么知道“哪些分片已经传过了”。这个记忆过程依赖两个东西第一文件的唯一标识。我用的是整个文件的 md5 值。文件内容确定md5就唯一确定同一文件哪怕改个文件名md5不变。这个值在文件第一次被用户选中时由前端计算出来之后每次上传分片、查询进度时都带上它。第二服务端的进度记录。后端收到分片后会按照“md5_序号.part”的格式把分片落盘。当用户重新上传时前端先用md5请求后端一个查询接口后端扫描临时目录里属于该md5的所有.part文件把已存在的分片序号做成数组返回给前端。WebUploader 拿到这个数组后跳过多余的分片直接排到缺失分片的位置继续传。这里要特别说明md5计算是前端做的后端不重复计算。前端算好整个文件的md5在请求参数里传给后端即可。有人会担心前端算md5耗时长1GB文件在现在的PC上用 WebUploader 内置的md5File方法大概也就几秒到十几秒相比上传耗时是可以接受的。但要注意计算过程中不能让浏览器卡死后面踩坑章节我会讲怎么处理。2.3 秒传与断点续传的关系断点续传往下延伸还能做“秒传”。原理非常简单既然md5能唯一标识文件用户选择文件计算完md5后先调一个检查接口后端发现该md5对应的完整文件已经存在直接返回“上传完成”前端连分片都不用传。这个机制在文件去重、资源仓库场景特别实用。我当前项目里把秒传和断点续传合到了同一个检查接口里后端逻辑一句话说清如果该md5文件已完整存在返回特殊标记is_exists: true前端直接跳完成否则返回已上传的分片序号列表供断点续传使用。3. 前后端完整实现从零搭一套分片上传接口3.1 环境准备和目录规划后端环境没有特殊要求只要 PHP 5.6 以上支持move_uploaded_file和file_put_contents即可。需要注意两件事第一个是上传大小限制。分片上传已经规避了upload_max_filesize对单文件大小的限制但post_max_size必须大于分片大小因为每个分片本身也是一个POST请求。保险起见post_max_size设为 8Mupload_max_filesize设为 8Mmax_execution_time设为 0不限制避免大分片合并时执行超时。建议修改PHP配置文件时顺手把内存限制memory_limit提到至少 256M合并分片时要读取和写入整个文件吃内存的隐患一直都在。目录规划建议这样project/ ├── upload/ │ ├── tmp/ # 分片临时存储目录 │ └── complete/ # 最终合并完成的文件目录tmp目录保存中间态的分片文件定期清理complete保存最终文件保持与业务对齐。两个目录都需要可写权限。3.2 前端WebUploader 初始化与核心参数页面里引入 WebUploader 的 CSS 和 JSWebUploader 依赖 jQuery需要提前引入。核心初始化代码!-- 引入依赖路径按自己项目调整 -- link relstylesheet hrefwebuploader.css / script srcjquery.min.js/script script srcwebuploader.min.js/scriptinput idpicker typebutton value选择文件 /var uploader WebUploader.create({ // 后端接收分片的地址 server: /upload.php, // 文件选择按钮 pick: #picker, // 选完文件后自动上传 auto: true, // 启用分片 chunked: true, // 每片大小2MB chunkSize: 2 * 1024 * 1024, // 同时上传的分片数建议3个太多会给PHP进程和磁盘IO造成压力 threads: 3, // 表单字段名后端用 $_FILES[file] 接收 fileVal: file, // 额外的全局参数会附加在每个分片请求里 formData: { type: upload } });前端有几个参数直接影响成败值得单列说明。chunked: true是分片总开关必须开chunkSize必须和规格匹配threads并发数不是越大越好并发太多时后端磁盘写入和Nginx连接数都会成为瓶颈建议3~5。fileVal这个参数容易被忽略默认是file如果前端改了这个名字后端$_FILES里的键名也得跟着改。还有一个容易踩的坑server地址后面不要带 query string比如/upload.php?typevideo。虽然WebUploader会保留这些参数但前端传md5和分片序号时如果后端用$_GET拿参数和原本的 query string 混在一起容易出问题。我统一把参数放formData里。3.3 文件级md5计算与状态注册WebUploader 在文件进入队列时会触发fileQueued事件。在这个事件里计算整个文件的md5并把md5作为自定义字段挂到文件对象上。uploader.on(fileQueued, function(file) { var md5 ; // 使用 WebUploader 提供的 md5File 方法计算全文件 md5 // 参数分别表示文件对象、计算起始位置、计算终止位置设为 -1 表示整个文件 uploader.md5File(file, 0, -1) .then(function(hashes) { // hashes 是数组类型这里取最后一个值作为全文件 md5 md5 hashes.pop(); file.md5 md5; // 把 md5 回传给后端后端用于分片存储路径与续传查询 uploader.option(formData, { file_md5: md5, type: upload }); }) .fail(function() { alert(文件特征值计算失败请重新选择文件); }); });新版 WebUploader 的md5File返回的是一个数组每个元素对应文件某个分片的md5数组最后一个元素才是整个文件的md5。这里有人直接拿取hashes[0]当成整个文件md5会有问题我测试时发现不同版本行为还不一样。稳妥做法是取最后一个元素并且以实际打印结果为准。由于md5File是异步的而且大文件计算耗时较长必须等待md5计算完成后再调用uploader.upload()否则分片先发出去了md5才计算完成后端拿不到文件标识整个断点续传就失效了。我的处理方式是初始化时先auto: false然后在md5计算完成的.then里手动触发uploader.upload()。3.4 前端上传前查询进度实现续传WebUploader 每次分片上传前默认不会主动查询哪些分片已存在。要在uploadBeforeSend事件里拦截查询后端进度后决定跳过哪些分片。uploader.on(uploadBeforeSend, function(block, data) { // 最重要的每个分片请求都带上 md5 和分片序号 data.file_md5 block.file.md5; data.chunk block.chunk; data.chunks block.chunks; });续传的查询动作通常放在“文件即将开始上传”的时机我用的是beforeUpload事件。这个事件在文件第一次开始上传或重传前触发在这个时机发起查询拿到已上传分片列表调用 WebUploader 的skip方法跳过分片。实际操作中查询接口返回已上传分片的编号数组然后循环标记跳过uploader.on(beforeUpload, function(file) { // 异步查询后端已上传的分片 $.ajax({ url: /check.php, method: POST, data: { file_md5: file.md5 }, dataType: json, success: function(res) { if (res.is_exists) { // 完整文件已存在直接不传了 uploader.skipFile(file); return; } // 已上传的分片编号数组 var uploadedChunks res.uploaded_chunks || []; // 遍历每个分片跳过已上传的 for (var i 0; i file.__chunks__; i) { if (uploadedChunks.indexOf(i) ! -1) { uploader.skip(file, i); } } // 跳过完之后正式开始上传缺失分片 uploader.upload(); } }); });这里要说明一下file.__chunks__这个参数它是 WebUploader 内部给文件对象挂的属性保存了当前文件实际的分片总数。在浏览器调试时直接打印file对象就能看到。高版本WebUploader里这个属性可能叫chunks我用的时候以实际打印为准。3.5 后端检查接口 check.php检查接口负责“记忆”查询和“秒传”判断逻辑比较集中?php // check.php $fileMd5 isset($_POST[file_md5]) ? $_POST[file_md5] : ; $tmpDir __DIR__ . /upload/tmp; $completeDir __DIR__ . /upload/complete; if ($fileMd5 ) { echo json_encode([code 1, msg 缺少文件标识]); exit; } // 幂等检查如果完整文件已经存在直接返回存在标记 $completeFile $completeDir . / . $fileMd5 . .mp4; if (file_exists($completeFile)) { echo json_encode([code 0, is_exists true]); exit; } // 扫描临时目录中属于这个md5的所有分片 $uploadedChunks []; $prefix $fileMd5 . _; foreach (glob($tmpDir . / . $prefix . *.part) as $partFile) { $basename basename($partFile); // 文件名格式{md5}_{chunk}.part if (preg_match(/^ . preg_quote($prefix) . (\d)\.part$/, $basename, $matches)) { $uploadedChunks[] (int) $matches[1]; } } echo json_encode([ code 0, is_exists false, uploaded_chunks $uploadedChunks ]);这里有个经验值得分享合并完成后的完整文件我按业务直接存成了.mp4。如果你无法预先知道文件类型建议把原始文件扩展名也通过表单参数传过来合并时拼上或者干脆不设扩展名由业务侧下载时再决定。glob扫描临时目录找分片这段逻辑在分片数量较大时可能会有点慢。但正常场景下几百个分片glob的性能是够用的没必要为这个上数据库。3.6 后端分片接收接口 upload.php这是整个方案最核心的接收口每次分片上传都会命中的就是这个接口。主要工作接收文件流用“md5_序号.part”命名保存到临时目录。?php // upload.php $fileMd5 isset($_POST[file_md5]) ? $_POST[file_md5] : ; $chunk isset($_POST[chunk]) ? intval($_POST[chunk]) : 0; $chunks isset($_POST[chunks]) ? intval($_POST[chunks]) : 0; if ($fileMd5 ) { echo json_encode([code 1, msg 缺少文件标识]); exit; } // 安全校验临时目录不能存储在暴露到公网的路径下 $tmpDir __DIR__ . /upload/tmp; if (!is_dir($tmpDir)) { mkdir($tmpDir, 0755, true); } // 检查是否上传了文件 if (!isset($_FILES[file]) || $_FILES[file][error] ! UPLOAD_ERR_OK) { echo json_encode([code 1, msg 上传分片失败]); exit; } if ($_FILES[file][size] 8 * 1024 * 1024) { echo json_encode([code 1, msg 分片大小超出上限]); exit; } // 分片文件名格式{md5}_{chunk}.part $partFile $tmpDir . / . $fileMd5 . _ . $chunk . .part; // 将临时文件移动到目标位置move_uploaded_file 保证只处理本次请求上传的文件 if (!move_uploaded_file($_FILES[file][tmp_name], $partFile)) { echo json_encode([code 1, msg 保存分片失败]); exit; } // 关键如果这是最后一个分片触发合并逻辑 if ($chunks 0 $chunk $chunks - 1) { // 这里不能直接合并因为最后一个分片到达不代表前面分片全部到达 // 需要调用独立的合并接口或在这里校验完整性 // 我的做法返回 success由前端最后主动触发合并 } echo json_encode([code 0, msg 分片上传成功]);后端分片接收有个重要细节move_uploaded_file不会去校验文件内容完整性。网络传输中途损坏的情况虽然少但存在。所以我在合并阶段会校验分片字节数是否和chunkSize匹配最后一片除外。如果想做更细的校验也可以让前端传每个分片的md5后端md5_file比对但对大部分场景来说这点收益和额外成本不成比例。最晚分片到达后不能立刻合并。原因在于并发上传时最后一个分片可能比前一个分片先到如果判定“最后一个分片到了就开始合并”会发现缺少前序分片。正确方案是由前端在全部上传完成事件里显式调用合并接口。3.7 前端全部传完后的合并触发WebUploader 在uploadFinished事件里表示所有分片都已上传成功。在这个事件里向后端请求合并uploader.on(uploadFinished, function() { var fileMd5 uploader.options.formData.file_md5; $.ajax({ url: /merge.php, method: POST, data: { file_md5: fileMd5, chunks: uploader.uploader.getFiles()[0].__chunks__ }, dataType: json, success: function(res) { if (res.code 0) { alert(文件上传成功); } else { alert(合并失败 res.msg); } } }); });需要注意如果uploadFinished触发时包含多文件需要遍历文件队列或根据file对象来定位。我这里简化了单文件逻辑多文件场景建议把文件标识和分片总数放到队列数据里保存。3.8 后端合并接口 merge.php合并接口做三件事校验所有分片齐全、按序号顺序写出完整文件、清理临时分片。?php // merge.php $fileMd5 isset($_POST[file_md5]) ? $_POST[file_md5] : ; $chunks isset($_POST[chunks]) ? intval($_POST[chunks]) : 0; if ($fileMd5 || $chunks 0) { echo json_encode([code 1, msg 参数错误]); exit; } $tmpDir __DIR__ . /upload/tmp; $completeDir __DIR__ . /upload/complete; if (!is_dir($completeDir)) { mkdir($completeDir, 0755, true); } // 校验分片是否齐全 for ($i 0; $i $chunks; $i) { $partFile $tmpDir . / . $fileMd5 . _ . $i . .part; if (!file_exists($partFile)) { echo json_encode([code 1, msg 缺少分片 . $i]); exit; } } $targetFile $completeDir . / . $fileMd5 . .mp4; // 如果目标文件已存在先删除避免重复合并导致内容叠加 if (file_exists($targetFile)) { unlink($targetFile); } // 按顺序写入使用二进制安全模式 $targetHandle fopen($targetFile, wb); if (!$targetHandle) { echo json_encode([code 1, msg 无法创建目标文件]); exit; } for ($i 0; $i $chunks; $i) { $partFile $tmpDir . / . $fileMd5 . _ . $i . .part; $partHandle fopen($partFile, rb); if (!$partHandle) { fclose($targetHandle); echo json_encode([code 1, msg 打开分片失败 . $i]); exit; } // 每片最多 2MB流式写入不会撑爆内存 while (!feof($partHandle)) { $buffer fread($partHandle, 8192); if ($buffer ! false) { fwrite($targetHandle, $buffer); } } fclose($partHandle); } fclose($targetHandle); // 合并后清理分片文件 for ($i 0; $i $chunks; $i) { $partFile $tmpDir . / . $fileMd5 . _ . $i . .part; if (file_exists($partFile)) { unlink($partFile); } } echo json_encode([code 0, msg 合并成功, url /upload/complete/ . $fileMd5 . .mp4]);合并这个环节皱眉点有两个。第一绝对不能拼字符串直接file_get_contents整个分片读到内存再写。一个2MB分片没问题但如果有用户传了上百个分片内存在循环里就会被吃满。fopen fread fwrite的流式写入才是正解边读边写内存占用恒定在很小范围。第二合并前一定要检查目标文件是否存在否则重复合并会造成目标文件内容翻倍。清理分片这个动作我放在合并成功后立即执行。这样可以避免临时目录里堆积几百个.part文件。但如果合并失败分片会保留在临时目录方便下次断点续传。这也是断点续传的容错机制合并失败不算白传重传时只需补上缺失的分片就行。4. 踩坑实录这些坑我花了一周才填平4.1 断点续传不生效全是session锁在作怪实现完第一版后我遇到一个诡异现象上传大文件时前端明明只发了3个并发分片请求但PHP日志显示后面的请求排了很长的队甚至超时。排查了一下午最后发现问题出在PHPSession上。PHP默认会为每个请求打开session文件并加锁直到脚本执行完毕或显式session_write_close()才释放。多个分片请求并发进来时第一个请求持有session锁后面的请求全都堵在等待锁释放那一步就跟单线程串行一样。解决办法有两个我用的是第一种在不需要使用session的接口里直接不启动session如果框架或公共逻辑里已经启动了调用session_write_close()手动释放锁。或者改存储比如把session存到Redis并发瓶颈会缓解很多但治标不治本因为锁逻辑还存在。上传分片这种接口压根不需要session存数据所以最佳做法是分片接收接口里不要启session已经在用的话exit前调用session_write_close()释放。4.2 使用了PATH_INFO模式后WebUploader分片参数丢失项目里框架是自研的路由用的是 PATH_INFO 模式比如/upload.php/uploadAction。WebUploader 的server配成这个地址后后端$_POST里死活拿不到chunk、chunks这些参数但$_FILES[file]又是正常的分片还是按整体文件上传的形态到达。原因很快定位Nginx 的 PATH_INFO 模式和普通查询字符串在解析上存在差异WebUploader 底层把分片参数放在POST formdata里某些配置下这些参数被Nginx吞了或者没走到PHP的$_POST。我的解决办法server直接指向不带 PATH_INFO 的权限脚本地址比如/server.php分片参数正常接收。如果你的框架必须走路由建议在路由配置里把这个接口单独豁免保证PHP能正确填充$_POST。这个坑花了我半天时间写出来给还在用 PATH_INFO 模式的朋友提个醒。4.3 md5计算耗时太长用户以为页面卡死了第一批内测用户反映“选完文件后整个页面像死了一样好几分钟没反应。”我一看500MB的视频文件md5File计算期间页面交互全部冻住。原因不复杂md5File在高版本WebUploader里被设计成了分批次计算它会把FileReader读取的结果在worker里处理但还是在主线程上跑的。代码层面我的业务逻辑拖慢了它——我当时在fileQueued事件里做了大量其他DOM操作还有就是用了低效的重复读取。解决办法有3个计算期间显示遮罩层loading效果明确告知用户“正在计算文件标识请稍候”。把大文件md5计算放进 Web Worker 里不让它阻塞主线程。WebUploader 是支持自定义md5计算逻辑的可以用 spark-md5 配合Web Worker实现。如果文件大小超过1GB考虑放弃整套文件md5改用文件大小最后修改时间文件名生成一个业务标识。虽然不完美但对上传成功率几乎没有影响而且不用付出整个文件读取计算的成本。实测下来普通的500MB文件用 WebUploader 内置md5计算大概7~10秒用户能接受超过1GB建议切换到方案三别让用户干等。4.4 Threads并发3分片总数量太少时并发形同虚设有个很隐蔽的问题前端设置threads: 3和chunkSize: 2MB但如果文件只有6MB总分片数才3个并发上限3个分片效果都一样。如果文件本身只有2MB切成了1个分片那分片上传就退化成普通上传。这个场景一般不是问题但要注意分片数量过少时断点续传的意义也不大。比如100KB的文件传一半断了重传成本本身就很低。所以这个方案最适合的文件区间是几十MB到几个GB。小于10MB的文件直接走普通上传反而更省事前端可以在fileQueued事件里判文件大小小文件用一个非分片的server地址。4.5 临时目录里分片越积越多磁盘爆了上线两个月后运维报警服务器磁盘使用率超过90%。一查是/upload/tmp里积压了大量.part文件全是用户传了一半就放弃的残留分片。解决方式我做了两层合并成功后立即清理分片代码里已经做了。增加一个每日清理计划遍历临时目录删除最后修改时间超过24小时的.part文件。断点续传虽然需要分片保留但用户在24小时内没继续传的分片基本可以认定不会再来补了。清理脚本用find配合-mtime 1就能完成如果你们的服务器有crontab加到每日任务里即可。4.6 大文件合并后的校验怎么确定文件是完整的合并完成后前端一般会以为万事大吉但后端最好再做一道校验。我的做法是合并完成后用PHP计算目标文件的md5和前端提交的file_md5比对。不一致说明合并过程可能出了问题返回错误码同时把分片重新保留等待重试。比对逻辑加在merge.php中目标文件写完后$actualMd5 md5_file($targetFile); if ($actualMd5 ! $fileMd5) { // 合并出错保留分片返回失败让前端重试 echo json_encode([code 1, msg 文件校验失败请重试]); exit; }md5_file对于大文件会一次性读入内存吗不会PHP内部对流式处理做了优化内存占用保持在较低水平。这一步校验虽然会多花一点时间但对“拼接出的文件能否被正常打开播放”起着决定性作用强烈建议加上。5. 性能优化与扩展方向当前方案的核心目标已经达成大文件稳定上传、断点续传、秒传、并发控制。但如果想把这套东西做得更成熟有3个方向值得扩展。第一个是使用更快的文件标识算法。md5计算耗时在高并发下还是略高可考虑关联后端存储逻辑做分片级增量校验前端只确认哪些分片没传不强行全文件md5。断点续传和秒传的判定可以用文件大小分片级md5来替代全文件md5效率高很多。第二个是合并后异步处理。某些视频文件合并后还要转码、抽帧、提取信息这些操作耗时较长如果放在merge.php里同步处理接口会被拖住。我的做法是接口只负责合并返回成功后把文件路径写入队列由另一个常驻进程处理后续加工。第三个是前端进度展示的精细优化。当前WebUploader自带整体进度已经够用但如果你想要显示每片的状态哪些传输中、哪些等待、哪些已重试可以监听uploadProgress事件自己构建分片状态列表。对于上传体验来说这一步往往是锦上添花用户对进度感知会更准确。就我个人实际操作里的体会而言这套方案虽然实现起来不算复杂但每个细节分片大小、并发数、session锁、md5计算时机、合并校验都能决定整个功能的上线质量。如果你现在也卡在大文件上传上建议不要一上来就追求功能全齐先把基础分片链路跑通再加上断点续传最后补秒传走一步稳一步比一次性上全方案更容易定位问题。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑