You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

NSURLSession与HLS视频缓存:如何删除未完成的部分下载文件?

解决AVAssetDownloadTask未完成下载内容的删除问题

我之前也碰到过一模一样的坑,折腾了好一阵才找到可行的解决办法,分享给你参考下:

核心问题根源

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

火山引擎 最新活动