123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- import UIKit
- import BFCommonKit
- import BFNetRequestKit
- open class PQDownloadManager: NSObject {
- static public let shared = PQDownloadManager()
- public let maxDownloadCount: Int = 1000
- public var batchDownloadData: [String: Any] = Dictionary<String, Any>.init()
- lazy public var sessionManager: PQSessionManager = {
- let sessionManager = PQSessionManager("downloadConfiguration")
- return sessionManager
- }()
-
-
-
-
-
-
-
-
-
- public func download(url: String, name: String? = nil, fileExtensionType: FileExtensionType?, imageURL: String? = nil, progressHandle: @escaping ProgressHandle, stateHandle: @escaping StateHandle) {
- BFLog(message: "开始下载文件:\(url)")
- let subfile = PQDownloadFileManager.downloadTotalFile()
- let newFileExtensionType: FileExtensionType = fileExtensionType ?? (FileExtensionType(rawValue: url.pathExtension) ?? FileExtensionType.normal)
- if (subfile?.count ?? 0) > 0 && (subfile?.count ?? 0) > maxDownloadCount {
- PQDownloadFileManager.removeDownloadFile(url: downloadDirectory + (subfile?.first)!, fileExtensionType: newFileExtensionType)
- }
- if !isValidURL(url: url) {
- BFLog(message: "文件地址为空:\(url)")
- return
- }
- let taskId = url.md5
- let absolutePath = url + ".\(newFileExtensionType.rawValue)"
- let localPath = PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: newFileExtensionType)
- let downloadLenght: Int64 = PQDownloadFileManager.downloadFileLength(url: absolutePath, fileExtensionType: newFileExtensionType)
- let downloadingTask: PQDownloadModel? = sessionManager.downloadTaskDatas.keys.contains(taskId) ? sessionManager.downloadTaskDatas[taskId] : nil
- var totalLength: Int64 = 0
- if downloadingTask != nil {
- totalLength = downloadingTask?.totalLength ?? 0
- }
- if downloadLenght > 0, (downloadingTask != nil && downloadingTask?.state == .compelte) || (totalLength > 0 && totalLength > downloadLenght) {
- progressHandle(1, downloadLenght, totalLength)
- BFLog(message: "文件已下载完成:\(url),downloadLenght = \(downloadLenght),totalLength = \(totalLength)")
- downloadingTask?.state = .compelte
- downloadingTask?.progress = 1
- postNotification(name: cDownloadMatrialSuccessKey, userInfo: ["code": "1", "url": url, "localPath": localPath, "fileExtensionType": newFileExtensionType])
- stateHandle(.compelte, url, localPath, nil)
- return
- }
- if downloadingTask != nil {
- var request = URLRequest(url: URL(string: url)!)
- request.setValue("bytes=%lld-\(downloadLenght)", forHTTPHeaderField: "Range")
- request.setValue("Accept-Encoding", forHTTPHeaderField: "identity")
- let task = sessionManager.session?.dataTask(with: request)
- task?.taskUrl = url
- task?.taskId = taskId
- downloadingTask?.task = task
- downloadingTask?.task?.resume()
- BFLog(message: "下载任务已存在继续下载:\(url),localPath = \(localPath)")
- } else {
- createDirectory(path: downloadDirectory)
- PQDownloadFileManager.removeDownloadFile(url: absolutePath, fileExtensionType: newFileExtensionType)
- BFLog(message: "URL(string: url)! ==\(URL(string: url)!)")
- var request = URLRequest(url: URL(string: url)!)
- request.setValue("Accept-Encoding", forHTTPHeaderField: "identity")
- let task = sessionManager.session?.dataTask(with: request)
- task?.taskUrl = url
- task?.taskId = taskId
- task?.resume()
- let tempModel = PQDownloadModel()
- tempModel.sourceURL = url
- tempModel.fileExtensionType = newFileExtensionType
- tempModel.progress = 0
- tempModel.state = .downloading
- tempModel.name = name
- tempModel.imageURL = imageURL
- tempModel.progressHandle = progressHandle
- tempModel.stateHandle = stateHandle
- tempModel.task = task
- BFLog(message: "新建下载任务:\(url),localPath = \(PQDownloadFileManager.downloadFileLocalPath(url: url, fileExtensionType: newFileExtensionType)),taskID:\(taskId) tempModel\(String(describing: tempModel.sourceURL))")
- if !sessionManager.downloadTaskDatas.keys.contains(taskId) {
- sessionManager.downloadTaskDatas[taskId] = tempModel
- }
- }
- }
-
-
-
-
-
-
- public func batchDownload(uniqueId: String, urls: [PQDownloadModel], downloadHandle: @escaping (_ isSuccess: downloadState, _ msg: String?, _ data: [String: Any]?) -> Void) {
- BFLog(message: "urls count is \(urls.count)")
- if urls.count <= 0 {
- return
- }
- if batchDownloadData.keys.contains(uniqueId) {
- BFLog(message: "这组任务已经在下载中\(uniqueId)")
- downloadHandle(.downloading, nil, nil)
- return
- }
- let dispatchGroup = DispatchGroup()
- var downloadInfo: [String: Any] = ["dispatchGroup": dispatchGroup]
- for downloadUrl in urls {
- if isValidURL(url: downloadUrl.sourceURL) {
- DispatchQueue.global().async(group: dispatchGroup, execute: DispatchWorkItem(block: {
- dispatchGroup.enter()
- PQDownloadManager.shared.download(url: downloadUrl.sourceURL ?? "", fileExtensionType: downloadUrl.fileExtensionType) { _, _, _ in
- } stateHandle: { _, _, _, _ in
- }
- }))
- }
- }
- downloadInfo["urls"] = urls
- downloadInfo["count"] = urls.count
- PQDownloadManager.shared.batchDownloadData[uniqueId] = downloadInfo
- dispatchGroup.notify(queue: DispatchQueue.main) {
- BFLog(message: "所有的已请求完成,tempArr = \(PQDownloadManager.shared.batchDownloadData[uniqueId] ?? [])")
- postNotification(name: cBatchDownloadMatrialSuccessKey, userInfo: ["uniqueId": uniqueId, "urls": PQDownloadManager.shared.batchDownloadData[uniqueId] ?? []])
- PQDownloadManager.shared.batchDownloadData.removeValue(forKey: uniqueId)
- }
- }
-
-
-
- @objc public func downloadMarial(notification: Notification) {
- let userInfo = notification.userInfo
- let url = userInfo?["url"] as? String
- let localPath = userInfo?["localPath"] as? String
- let code = userInfo?["code"] as? String
- BFLog(message: "目前下载的任务组数 \(PQDownloadManager.shared.batchDownloadData.keys)")
- PQDownloadManager.shared.batchDownloadData.forEach { _, value in
- var downloadInfo: [String: Any]? = value as? [String: Any]
- let urlsArr: [PQDownloadModel]? = downloadInfo?["urls"] as? [PQDownloadModel]
- let dispatchGroup: DispatchGroup? = downloadInfo?["dispatchGroup"] as? DispatchGroup
- var count: Int = downloadInfo?["count"] as? Int ?? 0
- if (urlsArr?.count ?? 0) > 0 {
- urlsArr?.forEach { downloadModel in
- if downloadModel.sourceURL == url {
- if code == "1" {
- downloadModel.filePath = localPath
- }
- BFLog(message: "count = \(count)")
- if count > 0 {
- BFLog(message: "leave = \(count)")
- count = count - 1
- downloadInfo?["count"] = count
- let dispatchGroupCount = dispatchGroup.debugDescription.components(separatedBy: ",").filter { $0.contains("count") }.first?.components(separatedBy: CharacterSet.decimalDigits.inverted).compactMap { Int($0) }.first
- BFLog(message: "dispatchGroup count is \(String(describing: dispatchGroupCount))")
- dispatchGroup?.leave()
- }
- }
- }
- }
- }
- }
-
-
-
-
-
- public class func downLoadFile(url: String, completionHandler: @escaping (_ filePath: String?, _ error: Error?) -> Void) {
-
- createDirectory(path: bgMusicDirectory)
- let filePath = bgMusicDirectory + url.md5 + ".mp3"
- let data = try? Data(contentsOf: NSURL.fileURL(withPath: filePath))
- if FileManager.default.fileExists(atPath: filePath) && (data?.count ?? 0) > 0 {
- DispatchQueue.main.async {
- completionHandler(filePath, nil)
- }
- } else {
- let session = URLSession.shared
- let request = URLRequest(url: URL(string: url)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 30.0)
- let dataTask = session.downloadTask(with: request) { url, _, error in
- if url != nil {
- if FileManager.default.fileExists(atPath: filePath) {
- try? FileManager.default.removeItem(atPath: filePath)
- }
- try? FileManager.default.moveItem(at: url!, to: URL(fileURLWithPath: filePath))
- DispatchQueue.main.async {
- completionHandler(filePath, nil)
- }
- } else {
- DispatchQueue.main.async {
- completionHandler(nil, error)
- }
- }
- }
- dataTask.resume()
- }
- }
- override private init() {
- super.init()
- addNotification(self, selector: #selector(downloadMarial(notification:)), name: cDownloadMatrialSuccessKey, object: nil)
- }
- open override func copy() -> Any {
- return self
- }
- open override func mutableCopy() -> Any {
- return self
- }
- }
|