如何在应用终止后恢复URLSessionDownloadTask下载任务?
重启应用后恢复URLSessionDownloadTask下载进度的实现方案
完全可以通过URLSessionDownloadTask实现,不需要额外依赖第三方库。核心是利用resumeData持久化和固定标识符的后台会话,步骤如下:
1. 暂停下载时保存恢复数据
当用户主动暂停下载,或者应用即将退出前,调用下载任务的cancel(byProducingResumeData:)方法生成恢复数据,将其持久化到本地(比如UserDefaults或文件,大文件推荐文件存储):
// 主动暂停下载时执行 self.task?.cancel { [weak self] resumeData in guard let resumeData = resumeData else { return } // 保存resumeData到UserDefaults UserDefaults.standard.set(resumeData, forKey: "DownloadResumeDataKey") }
2. 重启应用后恢复下载
应用启动时,优先读取本地保存的resumeData,用同一个后台会话标识符创建恢复任务;如果没有有效resumeData,再创建新下载任务:
self.fileDownloadUrl = "www.example.com" let sessionIdentifier = "com.example.app" // 尝试读取保存的恢复数据 if let resumeData = UserDefaults.standard.data(forKey: "DownloadResumeDataKey") { let config = URLSessionConfiguration.background(withIdentifier: sessionIdentifier) self.session = URLSession(configuration: config, delegate: self, delegateQueue: nil) // 通过resumeData恢复下载任务 self.task = self.session!.downloadTask(withResumeData: resumeData) self.task?.resume() } else if let downloadUrlStr = self.fileDownloadUrl, let fileUrl = URL(string: downloadUrlStr) { // 无恢复数据,创建新任务 let config = URLSessionConfiguration.background(withIdentifier: sessionIdentifier) self.session = URLSession(configuration: config, delegate: self, delegateQueue: nil) let request = URLRequest(url: fileUrl) self.task = self.session!.downloadTask(with: request) self.task?.resume() } else { self.unownedErrorPopUp.showAnimation() }
关键注意事项
- 后台会话的identifier必须固定,确保系统能关联会话状态。
- 处理resumeData失效:如果恢复下载失败(比如服务器资源变更),在
URLSessionDelegate的urlSession(_:task:didFailWithError:)方法中捕获.resumeDataInvalid错误,删除本地保存的resumeData后重新发起下载。 - 下载完成后,记得清除本地保存的resumeData,避免下次启动误触发恢复流程。
内容的提问来源于stack exchange,提问作者KimJitae
相关产品推荐
相关产品推荐

