uni.uploadFile 无法获取实时进度,必须使用 uni.createUploadTask 才能监听每 KB 进度;其返回 task 实例支持 onProgressUpdate,而 uni.uploadFile 返回 plain object 无此方法;多文件需独立 task 和进度变量,H5 支持 AbortController,App/小程序不支持;需节流更新 UI、控制并发、及时传入 tempFilePath 防静默失败。

直接用 uni.uploadFile 无法拿到实时进度 —— 它本身不提供进度回调,必须改用 uni.createUploadTask 才能监听每 KB 的上传状态。
为什么 uni.uploadFile 没有 onProgressUpdate?
因为 uni.uploadFile 是一个封装过的快捷方法,内部调用的是平台原生上传接口,但屏蔽了底层流式事件。它只暴露 success/fail,不暴露底层 progress event。真要进度,就得退一步用更底层的 uni.createUploadTask。
常见错误现象:uni.uploadFile({ ... }).onProgressUpdate 报错或静默失效 —— 这个链式调用根本不存在,是开发者误记成 uni.downloadFile 的写法。
-
uni.uploadFile返回 plain object(无方法);uni.createUploadTask返回 task 实例,带.onProgressUpdate() - H5 端支持
AbortController,App 和小程序不支持,取消任务只能靠后端标记 + 前端忽略后续回调 - 微信小程序要求 upload 域名在后台配置「request 合法域名」,否则连请求都发不出,更别说进度
uni.createUploadTask 怎么绑定到具体文件?
每个文件必须创建独立 task,并把进度更新作用到对应 UI 元素上。不能共用一个 progress 变量,否则多个文件上传时会互相覆盖。
实操建议:
- 给每条文件记录加字段:
progress: 0、status: 'pending'、taskId: 'upload_123' - 调用
uni.createUploadTask后,立刻用task.onProgressUpdate更新该文件的progress - 成功后设
status = 'success',失败则设status = 'failed',避免 UI 卡在“上传中” - 示例关键片段:
const task = uni.createUploadTask({ url: 'https://api.example.com/upload', filePath: file.tempFilePath, name: 'file', header: { Authorization: 'Bearer ' + token } }) task.onProgressUpdate(res => { // 注意:这里 res.progress 是 0–100 整数 this.fileList[file.index].progress = res.progress }) task.then(() => { this.fileList[file.index].status = 'success' }).catch(() => { this.fileList[file.index].status = 'failed' })
批量上传时怎么防 UI 卡死?
每 KB 触发一次 this.$forceUpdate() 或小程序的 this.setData(),几十个文件并发时 UI 直接卡住。进度更新必须节流。
实操建议:
- 用
setTimeout或requestAnimationFrame包一层,限制每秒最多更新 4~6 次 - 不要在
onProgressUpdate里直接调setData,先缓存变化,再批量提交 - App 端并发上传数受限(Android/iOS 通常 ≤8),需用队列控制,比如
p-limit或手写串行调度器 - 分片上传场景下,每片完成才更新
uploadedBytes,而不是每收到一个 chunk 就更新一次
最易被忽略的一点:iOS 和 Android 对临时文件路径的生命周期管理不同 —— iOS 的 tempFilePath 在上传中途被系统回收会导致任务静默失败,务必在 chooseFile 后立即传给 createUploadTask,不要做异步延迟处理。











