unicloud.uploadfile不适合大文件上传,因其本质依赖uni.uploadfile而受平台单文件大小和网络稳定性限制;必须采用前端分片+云函数流式合并方案,并通过数据库持久化分片状态实现断点续传。

uni-app 处理大文件上传必须绕开 uniCloud.uploadFile 单次直传限制,改用分片上传 + 云函数协同方案。前端不能直接传 50MB 以上的文件,否则会超时或被平台拦截。
为什么 uniCloud.uploadFile 不适合大文件
小程序和 App 端对单次 uni.uploadFile(注意不是 uniCloud.uploadFile)有严格限制:微信小程序单文件上限 50MB,H5 端受浏览器限制通常 200MB 左右,但实际网络不稳定时 10MB 就可能失败。而 uniCloud.uploadFile 虽然名义上支持更大体积,但它依赖底层平台的上传通道——在客户端调用时,本质仍是走 uni.uploadFile,所以同样受制于该限制。
- 常见错误现象:
uploadFile:fail timeout、uploadFile:fail Network Error、uploadFile:fail system error,尤其在弱网下高频出现 - 即使上传成功,也缺乏进度反馈,用户无法感知卡在哪个环节
- 重试成本高:整个文件重传,而非仅重传失败分片
分片上传必须由前端控制、云函数配合
真正可行的大文件方案是「前端分片 + 云函数合并」:前端把文件切块(如每块 2MB),逐个调用 uniCloud.uploadFile 上传到临时路径;云函数接收所有分片后,用 uniCloud.downloadFile 拉取、拼接、再存为完整文件。这个流程不能全交给前端,也不能全丢给云函数——前者没文件系统,后者拿不到 tempFilePath。
- 前端分片逻辑必须用
Blob.slice()或File.slice(),不能用 base64(内存爆炸) - 每个分片的
cloudPath必须带唯一标识,例如uploads/${fileId}/part-${index}.bin,避免覆盖 - 云函数需记录已上传分片数,用
db.collection('upload_tasks').doc(taskId).update()持久化状态,防止重复合并 - 合并完成后,务必调用
uniCloud.deleteFile清理所有分片,否则浪费存储空间
上传进度与中断续传怎么落地
进度不是靠估算,而是靠真实分片上传完成数。中断续传的关键在于服务端能识别“这个文件已传了哪几块”,而不是重新开始。
- 上传前先请求云函数生成
taskId和总分片数,存入本地localStorage或 Vuex - 每个分片上传时携带
{ taskId, index, total },云函数写入upload_parts集合,字段包括taskId、index、fileID、uploadedAt - 恢复上传时,查
upload_parts中taskId对应的已成功分片,跳过重传 - 不要依赖
uni.uploadFile的onProgressUpdate回调做整体进度——它只反映当前分片,且 H5 和小程序行为不一致
云函数合并时的几个硬坑
云函数内存和执行时间有限,合并操作极易超限。腾讯云函数默认超时 60 秒、内存 256MB;阿里云更严,超时 30 秒。直接读取几十个分片再拼接,大概率崩。
- 必须用流式合并:
fs.createReadStream+fs.createWriteStream,避免一次性readFileSync加载全部内容 - 合并前检查分片完整性:比对每个分片的
size字段是否匹配预期,防止中间某块传损 - 合并失败时,云函数要返回明确错误码(如
MISSING_PARTS),前端据此决定是重试还是提示用户手动修复 - 最终文件的
cloudPath必须带扩展名(如reports/20260618-abc123.pdf),否则 CDN 无法正确识别 MIME 类型
真正难的不是写分片逻辑,而是让前端和云函数在断网、杀进程、切换页面后还能对上状态。每个分片的元数据必须落库,每次操作都要幂等,fileID 一旦生成就不能再改——这些细节漏掉一个,用户就卡在“上传中”不动了。











