MAUI iOS通过FilePicker访问Nextcloud文件重启后访问被拒问题
选中的文件是否仅支持临时访问?
是,默认拿到的第三方File Provider文件路径仅在当前应用会话周期内有效。
你拿到的/private/var/mobile/Containers/Shared/AppGroup/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/File Provider Storage/开头的路径,是iOS系统为当前运行的应用进程临时开放的安全作用域路径,进程终止(应用重启、被系统回收)后,系统会自动回收该路径的访问授权,直接保存该路径下次启动访问时,就会触发你遇到的权限拒绝报错,这是iOS沙盒安全机制的预期行为,不是MAUI框架或者Nextcloud的bug。
无额外开发成本实现永久访问的方案
不需要自行实现WebDAV客户端,也不需要手动维护文件副本同步,直接使用iOS原生提供的**安全作用域书签(Security-Scoped Bookmark)**机制即可,具体操作逻辑如下:
- 当通过FilePicker选中文件拿到返回结果时,不要直接存储文件的绝对路径字符串,需要通过iOS平台特定代码获取文件对应的原生
NSUrl实例,调用该实例的书签生成方法,将返回的二进制书签数据持久化存储到应用本地(比如存在应用偏好设置、本地数据库中均可)。 - 应用重启后需要访问之前选中的文件时,取出本地存储的书签数据,通过系统提供的书签解析方法生成当前有效的文件访问URL,解析过程中系统会自动返回书签是否失效的标记,如果失效直接重新生成新书签覆盖存储即可。
- 每次访问文件前,调用URL对应的
StartAccessingSecurityScopedResource()方法申请当前进程的访问权限,文件读写完成后调用StopAccessingSecurityScopedResource()释放权限,避免资源泄漏。
该方案为系统原生支持的标准实现,对于Nextcloud这类通过File Provider接入系统文件管理的云存储服务,解析书签得到的访问地址始终指向源文件,读取时系统会自动拉取源文件的最新版本,不需要额外实现同步逻辑,也不会出现Android平台文件副本和源文件不一致的问题。
和Android平台行为的差异说明
Android平台FilePicker选中外部存储文件时,默认会将文件拷贝一份到应用私有缓存目录,你拿到的是本地副本的路径,所以应用重启后依然可以访问,但该副本不会和源文件自动同步,会存在版本不一致的问题;iOS的安全作用域书签方案是直接持有源文件的持久化访问授权,不存在本地副本,只要用户没有手动删除源文件、没有撤销应用的文件访问权限,授权就长期有效。
内容的提问来源于stack exchange,提问作者Sirius

