// // MP_DownloadManager.swift // MusicPlayer // // Created by 忆海16 on 2024/5/14. // import Foundation import Foundation import Tiercel class MP_DownloadManager: NSObject { static let shared = MP_DownloadManager() var session: SessionManager! var progressHandlers: [String: (CGFloat) -> Void] = [:] var completionHandlers: [URL: (Result) -> Void] = [:] var downloadTasks: [URL: URLSessionDownloadTask] = [:] var progressStorage: [String: CGFloat] = [:] // 新增进度存储 var songHandlers:[URL: MPPositive_SongItemModel] = [:] private override init() { super.init() var configuration = SessionConfiguration() configuration.timeoutIntervalForRequest = 60 configuration.maxConcurrentTasksLimit = 6 configuration.allowsCellularAccess = true session = SessionManager("com.yourApp.backgroundDownload", configuration: configuration) } func downloadVideo(from url: URL, song:MPPositive_SongItemModel, progressHandler: @escaping (CGFloat) -> Void, completion: @escaping (Result) -> Void) { progressHandlers[song.videoId] = progressHandler completionHandlers[url] = completion songHandlers[url] = song let downloadTask = session.download(url, headers: ["Accept-Encoding": "gzip, deflate"]) //配置进度条 downloadTask?.progress(handler: { [weak self] (task) in guard let self = self else {return} progressHandlers[song.videoId]?(task.progress.fractionCompleted) progressStorage[song.videoId] = task.progress.fractionCompleted }) //配置任务完成事件 downloadTask?.success(handler: { [weak self] (task) in guard let self = self else {return} //任务下载成功,进行文件转移 let originalURL = task.url //任务下载地址 let filePathUrl:URL = URL(fileURLWithPath: task.filePath) print("任务下载地址:\(filePathUrl)") let downloadsURL = DocumentsURL.appendingPathComponent("Downloads") if !FileManager.default.fileExists(atPath: downloadsURL.path) { do { try FileManager.default.createDirectory(at: downloadsURL, withIntermediateDirectories: true, attributes: nil) } catch { completionHandlers[originalURL]?(.failure(error)) return } } let fileURL = downloadsURL.appendingPathComponent("\(song.videoId ?? "").mp4") do { try FileManager.default.moveItem(at: filePathUrl, to: fileURL) //回调VideoID completionHandlers[originalURL]?(.success(songHandlers[originalURL]!)) progressStorage[song.videoId] = nil // 清除已完成任务的进度记录 } catch { completionHandlers[originalURL]?(.failure(error)) } //移除任务 if task.status == .succeeded { session.remove(task, completely: true) {_ in print("\(song.title ?? "")下载任务完成,移除任务") } } }).failure(handler: { [weak self] (task) in guard let self = self else {return} //任务下载失败 let originalURL = task.url if let error = task.error { completionHandlers[originalURL]?(.failure(error)) } if task.status == .failed { session.cancel(task) { _ in print("\(song.title ?? "")下载任务失败,取消任务") } } }) } func getProgress(for videoId: String) -> CGFloat? { return progressStorage[videoId] } func cancelAllTasksIfNeeded() { // 根据需求,取消所有任务,或者根据任务状态进行过滤 for key in progressStorage.keys { session.cancel(key) } } //删除下载文件 func deleteFileDocuments(_ videoId:String, completion:@escaping((String) -> Void)) { let downloadsURL = DocumentsURL.appendingPathComponent("Downloads") let fileURL = downloadsURL.appendingPathComponent("\(videoId).mp4") if FileManager.default.fileExists(atPath: fileURL.path) { do{ try FileManager.default.removeItem(at: fileURL) //文件删除成功 completion(videoId) print("成功删除了\(videoId)文件") }catch{ print("删除文件时发生错误:\(error)") } }else { print("文件不存在") } } }