触发didCompleteWithError后,如何用URLSession downloadTaskWithResumeData重启下载?
解决URLSession下载失败后用ResumeData重启的问题
Hey there! Let's walk through how to resume that failed second download using resumeData with URLSession, since you're stuck getting it to complete.
第一步:捕获下载失败时的ResumeData
当下载任务失败并触发urlSession(_:task:didCompleteWithError:)代理方法时,不是所有错误都能恢复,但如果服务器支持断点续传,系统会把恢复所需的resumeData放在错误对象的userInfo里。你需要从这里提取它:
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { guard let error = error else { // 任务成功完成,无需处理 return } // 从错误信息中提取resumeData if let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data { // 把resumeData存起来(可以存在属性、UserDefaults或本地文件) self.pendingResumeData = resumeData // 立即重启或者等待用户触发 restartFailedDownload() } else { // 没有可用的resumeData,比如服务器不支持断点续传、URL无效等 print("无法恢复下载:\(error.localizedDescription)") // 这种情况只能从头重新发起下载 startFreshDownloadForSecondFile() } }
第二步:用ResumeData重启下载
拿到有效的resumeData后,你可以用downloadTask(withResumeData:)创建一个新的下载任务,然后调用resume()启动它。这里可以用闭包或者代理模式,和你原来的下载逻辑保持一致就行:
func restartFailedDownload() { guard let resumeData = self.pendingResumeData else { return } // 创建恢复任务(这里用闭包示例,你也可以用代理模式) let resumeTask = defaultSession.downloadTask(withResumeData: resumeData) { [weak self] fileLocation, response, error in guard let fileLocation = fileLocation, error == nil else { print("重启下载失败:\(error?.localizedDescription ?? "未知错误")") return } // 把临时文件移到你的目标存储路径(替换成你自己的路径逻辑) guard let destinationURL = self?.getDestinationURL(for: response) else { return } do { // 先删除已存在的文件(如果有的话) if FileManager.default.fileExists(atPath: destinationURL.path) { try FileManager.default.removeItem(at: destinationURL) } try FileManager.default.moveItem(at: fileLocation, to: destinationURL) print("第二个文件下载重启并完成!") } catch { print("移动下载文件失败:\(error.localizedDescription)") } } // 启动恢复任务 resumeTask.resume() }
关键注意事项
- 服务器支持断点续传是前提:只有当服务器返回
Accept-Ranges: bytes响应头时,才能生成有效的resumeData。如果第二个文件的服务器不支持,你只能重新发起普通的downloadTask(with: url)。 - 检查第二个文件的失败原因:先在
didCompleteWithError里打印完整的错误信息,看看是网络超时、服务器错误还是URL问题。比如如果是URL无效,那恢复也没用,得先修正URL。 - 不要长期保存resumeData:有些服务器的resumeData会过期,最好在失败后立即尝试恢复,或者只临时存储。
- 保持Session一致性:如果用代理模式,恢复任务的URLSession要和原任务用同一个(或者配置相同的Session),避免出现意外问题。
内容的提问来源于stack exchange,提问作者tp2376
相关产品推荐
相关产品推荐

