必须在plus.downloadwgt完成后、plus.runtime.install前插入md5校验,否则cdn污染或传输中断会导致静默失败;需用plus.io filereader流式读取文件并配合sparkmd5计算哈希,ios须用plus.io.convertlocalfilesystemurl转换路径,android注意持久化路径与分块读取,失败后应删除损坏包、记录次数并支持回滚。

uni-app热更新资源包下载后怎么校验MD5
不能靠客户端「信任式加载」,必须在 plus.downloadWgt 完成后、plus.runtime.install 前插入校验环节。否则一旦wgt包被CDN缓存污染或传输中断,安装时会静默失败,用户看到的只是白屏或功能异常,日志里连错误都难捕获。
关键点在于:MD5不是可选步骤,而是热更新安全链的第一道闸门。uni-app本身不提供内置校验API,得自己读取下载后的文件内容并计算哈希。
- Android上wgt文件默认下载到
uni.getEnv().DOWNLOAD目录,路径形如_www/wgt/xxx.wgt或file:///data/user/0/xxx/cache/xxx.wgt - iOS上只能写入
NSCachesDirectory,路径需用plus.io.convertLocalFileSystemURL转换,直接拼接file://会失败 - 不要用
uni.downloadFile的tempFilePath—— 它在iOS上是临时沙盒路径,plus.io无法访问;必须用plus.downloadWgt或手动指定持久化路径
用plus.io读取wgt文件并计算MD5的实操要点
别碰原生加密库或第三方JS MD5实现——它们要么不支持二进制流(导致中文/图片资源校验失效),要么在iOS WKWebView里因Sandbox限制报错。正确做法是用 plus.io 的 FileReader + ArrayBuffer 流式读取,再喂给 SparkMD5(轻量、零依赖、支持分块)。
示例关键代码片段:
const reader = new plus.io.FileReader();
reader.onload = function(e) {
const buffer = e.target.result; // ArrayBuffer
const spark = new SparkMD5.ArrayBuffer();
spark.append(buffer);
const md5 = spark.end(); // 得到小写32位字符串
if (md5 !== expectedMd5) {
console.error('wgt MD5 mismatch:', md5, 'expected:', expectedMd5);
// 此处应清理临时文件、触发降级逻辑(如重试或回退)
}
};
reader.readAsArrayBuffer(fileEntry); // fileEntry 来自 plus.io.resolveLocalFileSystemURL
-
SparkMD5必须用 npm install spark-md5 引入,不能 CDN 加载——iOS WKWebView 不支持动态 script 标签执行 - 大wgt包(>10MB)别一次性读全——用
reader.readAsArrayBuffer分块读取,避免内存爆掉(尤其低端安卓机) - 务必在
plus.io.resolveLocalFileSystemURL回调里获取fileEntry,不要用uni.getEnv().DOWNLOAD拼路径,不同平台返回路径格式不一致
MD5校验失败后怎么优雅降级
校验失败 ≠ 立刻崩溃。真实场景中,可能是网络抖动导致下载不完整、CDN节点脏数据、或用户手动篡改了本地缓存。这时候直接弹「更新失败」框只会激怒用户。
- 先删除已损坏的wgt文件:
fileEntry.remove(),防止下次启动误加载 - 记录失败次数到本地存储(
uni.setStorageSync),连续3次失败就自动切换回「检查整包更新」逻辑 - 若配置了回滚版本,从
uni.getStorage读取上一版wgt路径,调用plus.runtime.install恢复——注意iOS不支持回滚,该逻辑需平台判断 - 上报错误到监控系统,字段至少包含:
platform、wgtUrl、downloadSize、calculatedMd5、expectedMd5
为什么不能把MD5校验塞进uni.getUpdateManager流程
uni.getUpdateManager 是黑盒封装,只暴露 onUpdateReady 和 applyUpdate,中间没有钩子插入手动校验。它内部走的是 plus.runtime.install 直接加载,跳过了文件完整性验证环节。
这意味着:如果你只依赖 uni.getUpdateManager,哪怕服务端update.json里写了 md5 字段,客户端也根本不会去比对——它只认 version 和 packageUrl。
- 真正可控的校验时机只有两个:
plus.downloadWgt的onstatechanged(状态=4时文件已落盘),或uni.downloadFile的success回调(但后者不适用于wgt安装) - 别试图用
uni.downloadFile下载wgt再手动install——iOS会拒绝非plus.downloadWgt下载的文件,报错Invalid wgt package - Android上虽能绕过,但失去热更新生命周期管理(比如后台下载、断点续传),实际维护成本更高
NSCachesDirectory 的路径转换和Android上多层目录嵌套导致的 resolveLocalFileSystemURL 失败——这些错误不会抛异常,只会让 fileEntry 为 null,后续所有操作静默跳过。











