uni.downloadFile在App端默认串行执行,并非不支持并发;需手动实现固定槽位+任务队列模型,注意tempFilePath隔离、权限配置、断点条件、文件完整性校验、限次带延迟重试及后台中断处理。

uni.downloadFile 在 App 端不支持并发?
不是不支持,是默认行为会串行——uni.downloadFile 在 iOS 和 Android 原生层实际走的是单线程 HTTP 请求队列,连续调用多个 uni.downloadFile 时,后一个会等前一个 complete 或 fail 后才真正发起。这不是 uni-app 的 bug,而是底层 WebView 和原生封装的保守策略。
实操建议:
- 必须手动控制并发数,不能无限制
for循环调用uni.downloadFile - 推荐用「固定数量的下载槽位 + 任务队列」模型,比如最多同时跑 3 个下载任务
- 每个
uni.downloadFile调用必须配独立的tempFilePath,否则 iOS 下可能因路径复用导致写入冲突或静默失败 - Android 端要注意
android.permission.WRITE_EXTERNAL_STORAGE(SDK android:requestLegacyExternalStorage="true"(SDK ≥ 29)配置,否则success回调里拿不到合法文件路径
怎么拿到真实下载进度和状态?
uni.downloadFile 的 onProgressUpdate 在 App 端表现不稳定:iOS 偶尔不触发,Android 频率低且不精确;更关键的是它不区分「已下载字节数」和「响应头 Content-Length 缺失」的情况,容易误判为 0% 卡死。
实操建议:
- 务必在
success回调里用uni.getFileInfo校验文件大小,防止服务端返回 200 但内容为空 - 不要依赖
onProgressUpdate做 UI 进度条主逻辑,改用「时间戳 + 预估速率」做平滑过渡(例如:每 300ms 更新一次,速率 = 已下载字节 / 耗时) - 对没有
Content-Length的响应,onProgressUpdate的totalBytesWritten恒为 0,此时只能显示「正在接收数据…」,不能显示百分比 - 记录每个任务的
taskId(自增 ID 或 URL hash),避免回调错乱
下载完成后的文件怎么持久化不被清理?
App 端的 tempFilePath 是临时路径,iOS 会在应用退到后台或内存紧张时被系统回收;Android 的 getTempFileURL 返回的路径也可能随 App 重启失效。直接存 tempFilePath 到数据库或下次启动读取,大概率失败。
实操建议:
- 下载成功后立刻用
uni.saveFile将文件移到uni.env.USER_DATA_PATH下,这是最安全的用户数据目录 - 保存时用文件名哈希(如
md5(url))+ 扩展名生成唯一路径,避免重名覆盖:${uni.env.USER_DATA_PATH}/dl_${hash}.apk - 调用
uni.saveFile后,必须检查返回的savedFilePath是否与预期一致,某些 Android 厂商 ROM 会擅自改写路径(如加 .tmp 后缀) - 不要用
uni.getFileSystemManager().copyFile替代uni.saveFile,前者在部分 Android 12+ 设备上权限受限,且不触发系统媒体扫描
如何实现断点续传和失败重试?
uni.downloadFile 原生不支持断点续传(即不带 Range 请求头),也没有内置重试机制。所谓“续传”其实是靠本地记录已下载字节、手动拼接请求头实现的,但前提是服务端支持 Accept-Ranges。
实操建议:
- 只对大文件(>10MB)且服务端明确返回
Accept-Ranges: bytes时才考虑断点;小文件直接重下更稳 - 记录每个任务的
downloadedBytes和lastModified,重试前先uni.getFileInfo检查本地文件是否完整 - 重试次数建议 ≤ 3 次,第 2 次起增加随机延迟(如
Math.random() * 1000 + 500),避免服务端被压爆 - 别在
fail回调里直接递归调用uni.downloadFile,容易栈溢出;改用setTimeout+ 计数器控制
最麻烦的其实是状态同步:前台页面关闭、锁屏、切后台时,下载可能被系统中断,但 JS 层收不到通知。得靠 plus.runtime.getProperty 拿原生任务 ID,再配合 plus.downloader(仅 App 端)做兜底——但这套 API 和 uni.downloadFile 不互通,意味着你要维护两套下载逻辑。多数场景下,老老实实走 uni.downloadFile + 合理重试 + 明确用户提示,比强行搞“完美续传”更可靠。











