Flutter iOS端偶现PathNotFoundException:无法获取文件长度问题求助
iPhone 草稿上传文件偶发
PathNotFoundException 问题排查与解决 核心原因分析
- iOS临时文件路径的时效性:直接上传时,系统通过文件选择器授予APP的是临时访问权限,返回的路径指向沙盒内的临时文件。当APP被后台回收、系统清理临时目录,或者间隔时间过长后,该路径对应的文件会被系统删除,导致读取时触发路径不存在异常。
- SQLite存储内容错误:如果存入草稿的是文件的原始临时路径,而非持久化的文件标识,就会出现路径失效的偶发问题——iOS不保证临时路径的长期有效性。
- 偶发触发场景:常见于APP重启后、后台驻留过久被系统回收后,或者系统自动清理临时文件目录时,此时草稿中的旧路径已无法指向有效文件。
可行解决方案
1. 存储文件的持久化书签(Bookmark Data)
不要直接存储文件路径,而是将选中文件的NSURL转换为书签数据存入SQLite。书签数据包含了文件的持久化访问权限,即使APP重启也能恢复有效URL并获取访问权限:
// 获取文件书签数据 NSData *bookmarkData = [selectedURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:nil]; // 将bookmarkData存入SQLite(需转为可存储的格式,比如Base64字符串) // 恢复URL并获取访问权限 NSData *storedBookmarkData = // 从SQLite读取的书签数据 BOOL isStale; NSURL *restoredURL = [NSURL URLByResolvingBookmarkData:storedBookmarkData options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:nil]; if (restoredURL) { [restoredURL startAccessingSecurityScopedResource]; // 执行文件上传操作 [restoredURL stopAccessingSecurityScopedResource]; }
2. 将文件复制到APP沙盒存储
选中文件后,先把文件复制到APP的Documents或Library目录,再将沙盒内的路径存入草稿。沙盒内的文件不会被系统自动清理,路径长期有效:
NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *targetFilePath = [documentsPath stringByAppendingPathComponent:[selectedURL lastPathComponent]]; NSURL *targetURL = [NSURL fileURLWithPath:targetFilePath]; // 复制文件到沙盒 NSError *error; if ([fileManager copyItemAtURL:selectedURL toURL:targetURL error:&error]) { // 将targetFilePath存入SQLite作为草稿路径 } else { // 处理复制失败逻辑 }
3. 上传前校验文件有效性
从草稿读取路径后,先检查文件是否存在,若不存在则提示用户重新选择文件,避免抛出异常:
NSString *storedPath = // 从SQLite读取的文件路径 NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:storedPath]) { // 提示用户:文件已失效,请重新选择 return; } // 执行上传操作
内容的提问来源于stack exchange,提问作者M.A.
相关产品推荐
相关产品推荐

