uni-app小程序大文件分片上传与断点续传实战 1. uni-app小程序大文件上传的痛点分析在uni-app开发小程序时文件上传功能是常见的业务需求。但当遇到大文件如视频、高清图片上传时开发者往往会面临一系列性能问题上传过程中页面卡顿甚至假死网络波动导致上传失败后需要重新开始上传进度反馈不及时内存占用过高导致小程序崩溃后台切换后上传任务中断这些问题在小程序运行环境下尤为突出因为小程序本身运行在沙盒环境中对内存和CPU的使用都有严格限制。以微信小程序为例单个JS线程的内存限制约为256MB超过这个限制就会触发系统回收机制。2. 技术方案选型与对比2.1 传统上传方案的局限性常规的上传方案是直接使用uni.uploadFile APIuni.uploadFile({ url: https://example.com/upload, filePath: tempFilePath, name: file, success: (res) { console.log(res.data); } });这种方案在小文件上传时表现良好但对于大文件存在明显缺陷无法断点续传没有分片机制进度回调频率低无法暂停/恢复上传2.2 优化方案的核心思路基于上述问题我们设计了分片上传断点续传的方案文件分片将大文件切割成多个小分片建议1-5MB并行上传同时上传多个分片注意控制并发数断点记录保存已上传分片信息失败重试单个分片上传失败自动重试进度聚合计算整体上传进度3. 具体实现步骤3.1 前端实现细节文件分片处理function sliceFile(file, chunkSize 1024 * 1024) { return new Promise((resolve) { const chunks []; let start 0; while (start file.size) { const end Math.min(start chunkSize, file.size); chunks.push({ chunk: file.slice(start, end), index: chunks.length, start, end }); start end; } resolve(chunks); }); }上传控制逻辑async function uploadChunks(chunks, uploaded []) { const MAX_CONCURRENT 3; // 控制并发数 const queue []; let current 0; for (let i 0; i chunks.length; i) { if (uploaded.includes(i)) continue; while (current MAX_CONCURRENT) { await Promise.race(queue); } current; const task uploadChunk(chunks[i]) .then(() { current--; uploaded.push(i); saveProgress(uploaded); // 保存进度 }) .catch(() { current--; }); queue.push(task); } await Promise.all(queue); return mergeChunks(); // 通知服务端合并分片 }3.2 服务端配合要点服务端需要实现三个关键接口分片上传接口接收单个分片并存储分片校验接口检查分片是否已上传分片合并接口将所有分片合并为完整文件建议的目录结构/uploads /{file_md5} /chunks 0.chunk 1.chunk ... info.json # 存储文件元信息4. 体验优化技巧4.1 进度反馈优化传统方案只提供粗略的上传进度我们可以实现更精细的反馈// 计算实时速度 let lastLoaded 0; let lastTime Date.now(); function onProgress({ loaded, total }) { const now Date.now(); const duration (now - lastTime) / 1000; const speed ((loaded - lastLoaded) / duration).toFixed(2); uni.$emit(upload-progress, { percent: (loaded / total * 100).toFixed(2), speed: ${speed} KB/s, remaining: calculateRemainingTime(loaded, total, speed) }); lastLoaded loaded; lastTime now; }4.2 内存优化策略使用Worker处理文件分片// upload.worker.js self.onmessage function(e) { const { file, chunkSize } e.data; const chunks sliceFile(file, chunkSize); self.postMessage(chunks); }; // 主线程 const worker new Worker(upload.worker.js); worker.postMessage({ file, chunkSize: 1024 * 1024 }); worker.onmessage function(e) { const chunks e.data; // 处理分片 };及时释放内存// 上传完成后释放文件引用 file null; chunks null;5. 异常处理与兼容性5.1 常见问题排查分片上传失败检查Content-Range头部是否正确验证分片MD5是否匹配确认服务端临时存储空间充足合并失败检查所有分片是否完整上传验证文件MD5是否一致检查文件权限设置5.2 多平台兼容方案针对不同平台做差异化处理function getUploadAPI() { // #ifdef MP-WEIXIN return wx.uploadFile; // #endif // #ifdef H5 return axios.post; // #endif // #ifdef APP-PLUS return plus.uploader.createUpload; // #endif }6. 性能对比数据我们针对10MB文件进行了测试对比指标传统方案优化方案上传时间32s18s内存峰值85MB42MB失败恢复重新开始断点续传CPU占用高中进度精度10%间隔1%间隔7. 扩展优化方向智能分片策略根据网络质量动态调整分片大小WiFi环境下增大分片移动网络减小分片后台持续上传// app.js onLaunch() { this.uploadManager new UploadManager(); this.uploadManager.resumeAll(); } onHide() { this.uploadManager.pauseAll(); }上传前压缩使用wasm进行图片/视频压缩根据网络状况调整压缩率在实际项目中我们通过这套方案将500MB视频上传的成功率从63%提升到了98%平均上传时间缩短了40%。关键是要根据具体业务场景调整分片大小和并发数找到最佳平衡点。