NSURLSession与HLS视频缓存:如何删除未完成的部分下载文件?
我之前也碰到过一模一样的坑,折腾了好一阵才找到可行的解决办法,分享给你参考下:
核心问题根源
AVAssetDownloadTask的未完成下载文件并不存在于你常规的应用下载目录里,而是存在系统管理的沙盒私有目录中,手动遍历找不到很正常,但系统设置会读取这些私有目录的内容来显示“已下载视频”。苹果文档只说了要自己删,但没给具体路径和方法,得靠AVFoundation和NSURLSession的API来获取并清理。
具体解决步骤
1. 给任务打标识,方便后续关联
创建AVAssetDownloadTask(包括多码率的AVAggregateAssetDownloadTask)时,给任务设置唯一的taskDescription,比如传入HLS流的URL哈希值或者业务唯一ID,同时把这个标识和任务的taskIdentifier存在本地存储(比如UserDefaults或CoreData),这样后续能快速定位到要清理的任务。
2. 取消任务时直接清理临时文件
不要直接调用task.cancel(),而是用cancel(byProducingResumeData:)方法,这个回调里的resumeData包含了临时文件的路径信息,解析后就能删除:
task.cancel(byProducingResumeData: { resumeData in guard let resumeData = resumeData else { return } do { // 解析resumeData获取临时文件路径 if let resumeDict = try JSONSerialization.jsonObject(with: resumeData, options: []) as? [String: Any], let localPath = resumeDict["NSURLSessionResumeInfoLocalPath"] as? String { let tempFileURL = URL(fileURLWithPath: localPath) let fileManager = FileManager.default // 如果是多码率下载,可能是目录,要递归删除 if fileManager.fileExists(atPath: tempFileURL.path) { try fileManager.removeItem(at: tempFileURL) // 同步删除本地存储的任务记录 } } } catch { print("清理临时下载文件失败:\(error.localizedDescription)") } })
3. 清理历史遗留的未完成任务
如果有之前取消但没清理的任务,可以在App启动时,通过AVAssetDownloadURLSession获取所有任务并处理:
downloadSession.getAllTasks { tasks in tasks.forEach { task in // 筛选出已取消/未完成的任务,通过taskDescription匹配你要清理的目标 if task.state == .canceling || (task.state == .completed && task.error != nil) { // 重复上面的cancel+清理逻辑 task.cancel(byProducingResumeData: { resumeData in // 解析并删除文件... }) } } }
4. 同步系统设置显示
删除文件后,系统设置里的“已下载视频”不会立即刷新,一般等待几分钟系统会自动同步,或者可以重启App加速更新。如果是涉及媒体库的下载,也可以调用MPMediaLibrary.default().update()触发同步。
苹果文档里那句“当下载被取消且不打算恢复时,应用负责删除已下载的部分资产”,实际就是要靠解析resumeData拿到路径来实现,亲测这个方法能彻底删除临时文件,系统设置里的记录也会消失。
内容的提问来源于stack exchange,提问作者Momentus Mitch




