后台URLSession上传文件:删除下载文件失败+任务未启动求助
iOS后台URLSession上传文件问题解答
问题场景
使用后台URLSession上传两个文件,任务创建代码如下:
let backgroundTask = self.session.uploadTask(with: request, fromFile: src) backgroundTask.resume()
遇到两个问题:
- 第一个任务出现下载文件相关错误:
2023-08-05 22:35:50.609529-0700 BackgroundSession <19D89BF2-2E43-42D8-BAB8-F35D9FCBC291> FAILED to UNLINK download file: /private/var/mobile/Containers/Data/Application/57024651-0F4B-4181-A946-D08EC59E3578/Library/Caches/com.apple.nsurlsessiond/Downloads/com.foo.Bar/CFNetworkDownload_OhdFS5.tmp, errno:2, desc: No such file or directory
- 第二个文件上传任务已提交,但系统从未启动,无代理回调触发。
环境:Xcode 14.2,iOS 15.5(仅真机出现,模拟器正常)
问题一:上传任务为何出现下载文件相关错误?
这是后台URLSession的机制导致的命名混淆,并非真的触发了下载任务:
- 后台会话的
uploadTask(with:fromFile:)会将你传入的源文件复制一份到nsurlsessiond守护进程的专属临时目录,这个目录被命名为Downloads(苹果的命名逻辑问题,和下载任务无关); - 上传完成后,系统会尝试删除这个临时副本,错误中的
errno:2(文件不存在)说明临时文件已提前消失,可能的原因:- 上传过程中你主动删除了源文件,导致系统复制临时文件的过程中断;
- iOS低存储空间时,系统自动清理了
nsurlsessiond的临时缓存目录; - iOS 15.x版本的
NSURLSession后台会话存在临时文件管理的小bug,偶尔会出现此类异常。
问题二:后台上传任务停滞无回调的原因及排查方法
可能原因
- 会话配置错误:使用了非后台专用的配置,或
discretionary设为true(系统会延迟执行任务); - 应用被系统终止:应用在后台被系统杀掉后,未完成的后台任务可能无法重新调度;
- 文件异常:第二个文件不存在、路径错误或无读取权限;
- 任务超限:后台会话同时执行的任务数量达到系统限制,新任务进入排队;
- 网络/系统限制:设备处于低电量模式、蜂窝网络被限制,或
allowsCellularAccess配置错误。
排查步骤
- 检查会话配置:确保用
URLSessionConfiguration.background(withIdentifier:)创建会话,标识符唯一;若需立即执行任务,将discretionary设为false; - 验证文件状态:用
FileManager检查文件是否存在、路径是否正确、是否有读取权限:let fileExists = FileManager.default.fileExists(atPath: src.path) let attributes = try? FileManager.default.attributesOfItem(atPath: src.path) - 查看系统日志:在Xcode的「Devices and Simulators」中选中真机,打开Console,搜索
nsurlsessiond关键字,查看是否有任务被拒绝、排队的日志; - 确认应用生命周期:确保应用进入后台时没有调用
invalidateAndCancel()终止会话,或finishTasksAndInvalidate()导致不再接受新任务; - 测试环境:关闭低电量模式,切换到Wi-Fi环境,确认
allowsCellularAccess配置符合需求; - 重置守护进程:重启设备,重置
nsurlsessiond的状态,排除进程异常问题。
内容的提问来源于stack exchange,提问作者user1783732
相关产品推荐
相关产品推荐

