TSCommonTool+MultDown.swift 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. //
  2. // MultiTaskDown.swift
  3. // Pods
  4. //
  5. // Created by 100Years on 2025/3/17.
  6. //
  7. public extension TSCommonTool {
  8. // /// 多任务下载并缓存文件,依据 URL 的后缀名动态设置文件名
  9. // /// - Parameters:
  10. // /// - url: 文件的 URL 地址
  11. // /// - completion: 完成回调,返回本地缓存路径或错误
  12. // public static func multidownloadAndCacheFile(
  13. // from urlString: String,
  14. // fileEx:String? = nil,
  15. // cacheDirectory:String = "cacheAll",
  16. // progressHandler: @escaping (Double) -> Void,
  17. // completion: @escaping (String?, Error?) -> Void) -> TSMultiTaskDownloader?
  18. // {
  19. //
  20. // guard let url = URL(string: urlString) else{
  21. // completion(nil, NSError(domain: "url null", code: 0))
  22. // return nil
  23. // }
  24. //
  25. //
  26. // if !urlString.contains("http") && urlString.contains("/"){
  27. // completion(urlString.fillCachePath, nil)
  28. // return nil
  29. // }
  30. //
  31. // let fileManager = FileManager.default
  32. //
  33. // // 获取缓存目录下的 `cacheVideo` 文件夹路径
  34. // let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
  35. // let cacheVideoDirectory = cachesDirectory.appendingPathComponent(cacheDirectory)
  36. //
  37. // // 创建 `cacheVideo` 文件夹(如果不存在)
  38. // if !fileManager.fileExists(atPath: cacheVideoDirectory.path) {
  39. // do {
  40. // try fileManager.createDirectory(at: cacheVideoDirectory, withIntermediateDirectories: true, attributes: nil)
  41. // } catch {
  42. // completion(nil, error)
  43. // return nil
  44. // }
  45. // }
  46. //
  47. // var fileName = url.path.md5
  48. //
  49. // // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
  50. // var fileExtension = fileEx
  51. // fileExtension = fileExtension ?? (url.pathExtension.isEmpty ? "" : url.pathExtension)
  52. // if let fileExtension = fileExtension,fileExtension.count > 0 {
  53. // fileName = url.path.md5 + ".\(fileExtension)"
  54. // }
  55. //
  56. // let cachedFileURL = cacheVideoDirectory.appendingPathComponent(fileName)
  57. //
  58. // //检查文件是否已存在于缓存中
  59. // if fileManager.fileExists(atPath: cachedFileURL.path) {
  60. // print("文件已存在于缓存中: \(cachedFileURL)")
  61. // completion(cachedFileURL.path, nil)
  62. // return nil
  63. // }
  64. //
  65. //
  66. // let downloader = TSMultiTaskDownloader.shared
  67. //
  68. // let url1 = URL(string: "https://example.com/file1.zip")!
  69. // let url2 = URL(string: "https://example.com/file2.zip")!
  70. //
  71. // downloader.downloadFile(from: url, progressHandler: { progress in
  72. // print("Download progress for file1: \(progress * 100)%")
  73. // progressHandler(progress)
  74. // }, completionHandler: { tempFileURL, error in
  75. // if let error = error {
  76. // DispatchQueue.main.async {
  77. // completion(nil, error)
  78. // }
  79. // return
  80. // }
  81. //
  82. // guard let tempFileURL = tempFileURL else {
  83. // DispatchQueue.main.async {
  84. // completion(nil, NSError(domain: "DownloadError", code: -1, userInfo: [NSLocalizedDescriptionKey: "临时文件路径不存在"]))
  85. // }
  86. // return
  87. // }
  88. //
  89. // do {
  90. // if fileManager.fileExists(atPath: cachedFileURL.path) {
  91. // try fileManager.removeItem(atPath:cachedFileURL.path)
  92. // dePrint("下载成功,移除已有的旧文件: \(cachedFileURL)")
  93. // }
  94. // try fileManager.moveItem(at: tempFileURL, to: cachedFileURL)
  95. // dePrint("文件下载并缓存成功: \(cachedFileURL)")
  96. // DispatchQueue.main.async {
  97. // completion(cachedFileURL.path, nil)
  98. // }
  99. // } catch {
  100. // dePrint("文件下载成功,但失败:\(error)")
  101. // DispatchQueue.main.async {
  102. // completion(nil, error)
  103. // }
  104. // }
  105. // })
  106. //
  107. // return downloader
  108. // }
  109. /// 多任务下载并缓存文件,依据 URL 的后缀名动态设置文件名
  110. /// - Parameters:
  111. /// - url: 文件的 URL 地址
  112. /// - completion: 完成回调,返回本地缓存路径或错误
  113. public static func multidownloadAndCacheFile(
  114. from urlString: String,
  115. fileEx:String? = nil,
  116. cacheDirectory:String = "cacheAll",
  117. progressHandler: @escaping (Double) -> Void,
  118. completion: @escaping (String?, Error?) -> Void) -> TSMultiTaskDownloader?
  119. {
  120. guard let url = URL(string: urlString) else{
  121. completion(nil, NSError(domain: "url null", code: 0))
  122. return nil
  123. }
  124. guard let cachedFileURL = checkURLString(
  125. from: urlString,
  126. fileEx: fileEx,
  127. cacheDirectory: cacheDirectory,
  128. progressHandler: progressHandler,
  129. completion: completion
  130. ) else {
  131. return nil
  132. }
  133. let fileManager = FileManager.default
  134. //检查文件是否已存在于缓存中
  135. if fileManager.fileExists(atPath: cachedFileURL.path) {
  136. print("文件已存在于缓存中: \(cachedFileURL)")
  137. completion(cachedFileURL.path, nil)
  138. return nil
  139. }
  140. let downloader = TSMultiTaskDownloader.shared
  141. downloader.downloadFile(from: url, progressHandler: { progress in
  142. print("Download progress for file1: \(progress * 100)%")
  143. progressHandler(progress)
  144. }, completionHandler: { tempFileURL, error in
  145. if let error = error {
  146. DispatchQueue.main.async {
  147. completion(nil, error)
  148. }
  149. return
  150. }
  151. guard let tempFileURL = tempFileURL else {
  152. DispatchQueue.main.async {
  153. completion(nil, NSError(domain: "DownloadError", code: -1, userInfo: [NSLocalizedDescriptionKey: "临时文件路径不存在"]))
  154. }
  155. return
  156. }
  157. do {
  158. if fileManager.fileExists(atPath: cachedFileURL.path) {
  159. try fileManager.removeItem(atPath:cachedFileURL.path)
  160. dePrint("下载成功,移除已有的旧文件: \(cachedFileURL)")
  161. }
  162. try fileManager.moveItem(at: tempFileURL, to: cachedFileURL)
  163. dePrint("文件下载并缓存成功: \(cachedFileURL)")
  164. DispatchQueue.main.async {
  165. completion(cachedFileURL.path, nil)
  166. }
  167. } catch {
  168. dePrint("文件下载成功,但失败:\(error)")
  169. DispatchQueue.main.async {
  170. completion(nil, error)
  171. }
  172. }
  173. })
  174. return downloader
  175. }
  176. //检查 url 对不对
  177. public static func checkURLString(
  178. from urlString: String,
  179. fileEx:String? = nil,
  180. cacheDirectory:String = "cacheAll",
  181. progressHandler:((Double) -> Void)? = nil,
  182. completion:((String?, Error?) -> Void)? = nil
  183. )->URL?
  184. {
  185. guard let url = URL(string: urlString) else{
  186. completion?(nil, NSError(domain: "url null", code: 0))
  187. return nil
  188. }
  189. if !urlString.contains("http") && urlString.contains("/"){
  190. completion?(urlString.fillCachePath, nil)
  191. return nil
  192. }
  193. let fileManager = FileManager.default
  194. // 获取缓存目录下的 `cacheVideo` 文件夹路径
  195. let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
  196. let cacheVideoDirectory = cachesDirectory.appendingPathComponent(cacheDirectory)
  197. // 创建 `cacheVideo` 文件夹(如果不存在)
  198. if !fileManager.fileExists(atPath: cacheVideoDirectory.path) {
  199. do {
  200. try fileManager.createDirectory(at: cacheVideoDirectory, withIntermediateDirectories: true, attributes: nil)
  201. } catch {
  202. completion?(nil, error)
  203. return nil
  204. }
  205. }
  206. var fileName = url.path.md5
  207. // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
  208. var fileExtension = fileEx
  209. fileExtension = fileExtension ?? (url.pathExtension.isEmpty ? "" : url.pathExtension)
  210. if let fileExtension = fileExtension,fileExtension.count > 0 {
  211. fileName = url.path.md5 + ".\(fileExtension)"
  212. }
  213. let cachedFileURL = cacheVideoDirectory.appendingPathComponent(fileName)
  214. return cachedFileURL
  215. }
  216. //获取 urlstring 本地的缓存 url path
  217. public static func getCachedURLString(
  218. from urlString: String,
  219. fileEx:String? = nil,
  220. cacheDirectory:String = "cacheAll")->URL?{
  221. if let cachedFileURL = checkURLString(
  222. from: urlString,
  223. fileEx: fileEx,
  224. cacheDirectory: cacheDirectory
  225. ){
  226. //检查文件是否已存在于缓存中
  227. if FileManager.default.fileExists(atPath: cachedFileURL.path) {
  228. print("文件已存在于缓存中: \(cachedFileURL)")
  229. return cachedFileURL
  230. }
  231. }
  232. return nil
  233. }
  234. }