app端批量删文件需串行调用uni.removesavedfile或改用plus.io;前者仅支持uni.savefile保存的临时文件,后者可删_doc等目录文件,但需注意android 11+沙箱限制及路径校验。

App端调用uni.removeSavedFile批量删文件会失败?
直接循环调用uni.removeSavedFile大概率删不干净,甚至静默失败——它本质是异步 API,没加await或没处理fail回调时,多个请求会并发挤在原生层,iOS 尤其容易丢回调、Android 可能报fail no such file or directory(其实文件还在)。这不是 uni-app bug,是原生文件系统对并发删除的限制。
实操建议:
- 必须用
async/await串行执行,别用forEach + Promise并发 - 每次调用后检查
res.errMsg是否含ok,不是就记日志,别跳过 - 路径必须和保存时完全一致,包括大小写、斜杠方向(App 端一律用
/,别用\) - 删前可用
uni.getSavedFileList先确认文件是否存在,避免无谓调用
为什么plus.io比uni.removeSavedFile更适合批量删?
uni.removeSavedFile只支持删“通过 uni.saveFile 保存的临时文件”,而 App 端真正要删的往往是下载到 _doc 或 _downloads 目录下的业务文件(比如 PDF、Excel),这些根本不在它的管辖范围。这时候得切到 plus.io 原生 IO 接口。
实操建议:
- 先用
plus.io.resolveLocalFileSystemURL获取目录句柄,再用entry.removeRecursively递归删整个文件夹(比单个删快得多) - 注意权限:Android 10+ 需在
manifest.json里配置"androidPermissions": ["android.permission.WRITE_EXTERNAL_STORAGE"],且运行时申请 - iOS 上
_downloads目录不可写,只能删_doc或_www下的子目录 - 删完务必调用
plus.io.scanDirectory触发媒体库刷新,否则相册/文件管理器里还显示旧文件
删文件前怎么安全判断路径是否合法?
用户传个 ../../../etc/passwd 这种路径进来,plus.io 会直接报错退出,但错误信息极不友好(Invalid argument),根本看不出是路径越界。uni-app 没内置路径校验,得自己拦。
实操建议:
- 用正则过滤掉
..和绝对路径开头(^/或^[a-zA-Z]:\) - 统一用
plus.io.convertLocalFileSystemURL把相对路径转成绝对 URL,再用url.startsWith(plus.io.convertLocalFileSystemURL('_doc'))判断是否在允许范围内 - 对 iOS,额外检查路径是否含
Library/Caches或tmp—— 这些目录系统会自动清理,不该手动碰 - 别信前端传来的路径字符串,服务端也要做二次校验(如果涉及上传/下载链路)
安卓 11+(API 30)批量删文件的兼容陷阱
启用了 android:requestLegacyExternalStorage="false" 后,plus.io 对 _downloads 目录的写权限直接失效,removeRecursively 会返回 IO error: Permission denied。这不是代码问题,是 Android 存储沙箱强制升级的结果。
实操建议:
- 目标 API ≥ 30 时,改用
MediaStoreAPI 删除媒体类文件(图片、视频、音频),用DocumentFile删除文档类文件 - uni-app 暂未封装这些,需写原生插件或调用
uni.requireNativePlugin调用已有的开源插件(如uni-file-picker的底层逻辑) - 非媒体/文档类文件(比如缓存的 JSON、加密数据),老老实实存在
plus.io.getBasePath() + '/cache/'下,这个路径始终可写 - 别试图绕过沙箱——
requestLegacyExternalStorage在新机型上已无效,审核也会被拒
最麻烦的不是怎么删,而是删之前得想清楚:这个文件到底属于哪个存储域(uni 临时区 / plus.io 沙箱 / MediaStore / DocumentProvider),每个域的删除方式、权限要求、生命周期都不同。漏判一个,轻则删不掉,重则引发崩溃或审核风险。











