app端离线缓存必须用plus.io存文件+uni.setstoragesync存元数据+显式校验,因uni.setstorage仅适合小配置,存大文件会导致卡死、丢数据、ios静默失败。

App端离线缓存和断网恢复不能靠 uni.setStorage 单打独斗——它只适合存小配置,存图片、HTML、JSON文件会卡死、丢数据、iOS写入静默失败。真要落地,必须用 plus.io 存文件 + uni.setStorageSync 存元数据 + 显式校验机制。
为什么 uni.setStorage 在 App 端扛不住离线缓存?
它本质是字符串序列化存储,不是文件系统。一旦你试图缓存一张 1.5MB 的商品图或一个含内联 CSS/JS 的 HTML 页面,就会触发以下问题:
-
plus.storage写入大对象时无报错但实际未落盘(尤其 iOS) - 读取后
JSON.parse报Unexpected token(字符串被截断或 UTF-8 编码损坏) - Android 后台进程被杀、iOS 进入 suspend 后,异步写入的数据大概率丢失
- H5 端 localStorage 有 5MB 硬限制,App 端虽无硬限,但主线程阻塞会导致 UI 卡顿甚至崩溃
怎么用 plus.io 安全存离线资源?
这是唯一能模拟“离线包”语义的方案:把远程 URL 下载成本地文件,后续直接加载。关键不是“能不能存”,而是“存哪、怎么读、怎么防丢”:
- 必须用
plus.io.PRIVATE_DOC目录——App 可读写,且不会被系统自动清理 - 文件路径必须经
plus.io.convertLocalFileSystemURL(path)转换,否则<web-view></web-view>或uni.loadSubNVue无法识别 - 下载前调用
plus.runtime.getDiskInfo()检查剩余空间,避免写满导致后续所有 IO 失败 - 文件名建议用 URL 的 MD5 值(如
md5('https://api.example.com/detail.json')),避开斜杠、问号等非法字符 - 不要直接覆盖写:先写
detail.json.new,再moveTo替换原文件,保证原子性(plus.io没事务)
断网时如何安全恢复数据并避免“空路径”陷阱?
恢复不是读个 storage 就完事。路径还在,文件可能已被系统清理、用户手动删除,或下载中途中断残留了半成品:
- 所有文件路径必须存在
uni.env.USER_DATA_PATH下,不能用uni.saveFile(它可能写进tmp目录,iOS 会清) - 恢复前必须调用
uni.getFileSystemManager().access({ path })显式校验文件真实存在,success才读,fail则降级处理(如提示“缓存失效,请重试”) - 结构化小数据(如用户偏好、最后操作时间)可用
uni.setStorageSync,但别存 >1MB 对象,否则卡主线程 - 关键数据建议加版本字段,例如
uni.setStorageSync('order_cache_v2', { version: 2, data: ... }),防止旧逻辑误读新结构
怎么让离线包支持增量更新和回滚?
离线包不是“一次下载永久有效”。服务端必须提供 manifest.json,包含每个资源的 url、md5、size 和 timestamp:
- App 启动时比对本地
manifest.json与服务端版本,只下载md5不一致或缺失的文件 - 下载完成前保留旧版
manifest.json和全部资源,确保异常中断后下次启动仍可用 - 更新采用“先写 .new → 再 rename”策略,避免半更新状态导致页面白屏或 JS 报错
- 不要依赖客户端时间做过期判断——用服务端返回的
timestamp,避免设备时间不准引发误判
最易被忽略的一点:所有文件 IO 操作必须配超时和重试(尤其是弱网环境),且 plus.io 的错误回调里没有详细错误码,得靠 console.log + 真机日志定位 —— 模拟器根本看不出磁盘满或权限拒绝的问题。











