Swift 下载功能

1,275 阅读1分钟

apple 官方文档

  • 在Library/Caches 的目录下创建 Music 文件夹
let musicPath = NSHomeDirectory() + "/Library/Caches/Music"
do {
    try FileManager.default.createDirectory(atPath: musicPath, withIntermediateDirectories: true, attributes: nil)
} catch  {
    print(error.localizedDescription)
}

简单下载

guard let url = URL(string: "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview118/v4/49/3a/a3/493aa3e4-908d-9716-f7d7-cb01c0edbf3d/mzaf_1133582187629104439.plus.aac.p.m4a") else { return }
let fileName = url.lastPathComponent // 用下载链接的后缀当作文件名
let savePath = musicPath + "/" + fileName // 保存的路径
let downloadTask = URLSession.shared.downloadTask(with: url) { (url, response, error) in
    guard let fileURL = url else { return }
    do {
        try FileManager.default.moveItem(atPath: fileURL.path, toPath: savePath)
    } catch {
        print("file error: \(error)")
    }
}
downloadTask.resume()

获取下载进度 遵循 URLSessionDownloadDelegate 协议

private lazy var urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
private var downloadTask:URLSessionDownloadTask?
  • 开始下载
downloadTask = urlSession.downloadTask(with: url)
downloadTask?.resume()
  • URLSessionDownloadDelegate
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        
        do {
            try FileManager.default.moveItem(atPath: location.path, toPath: savePath)
            print("下载完成")
        } catch {
            print("file error: \(error)")
        }
    }
    
    // 读取下载进度
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        
        if downloadTask == downloadTask {
            let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file) // 总大小 MB
            let downLoadedSize = ByteCountFormatter.string(fromByteCount: totalBytesWritten, countStyle: .file)
            let calculatedProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
            DispatchQueue.main.async {
                print("总大小: \(totalSize) , 已下载: \(downLoadedSize), 进度: \(calculatedProgress)")
                
            }
        }
    }

后台下载

  • 遵循 URLSessionDelegate,URLSessionDownloadDelegate
private var resumeData:Data?
    
private var sessionDownloadTask:URLSessionDownloadTask?
    
private lazy var urlSession:URLSession = {
        let config = URLSessionConfiguration.background(withIdentifier: "MySession")
        config.isDiscretionary = true
        config.sessionSendsLaunchEvents = true
        return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()
  • 开始下载
guard let url = URL(string: "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview118/v4/49/3a/a3/493aa3e4-908d-9716-f7d7-cb01c0edbf3d/mzaf_1133582187629104439.plus.aac.p.m4a") else { return }
let fileName = url.lastPathComponent // 用下载链接的后缀当作文件名
savePath = musicPath + "/" + fileName // 保存的路径
sessionDownloadTask = urlSession.downloadTask(with: url)
sessionDownloadTask?.resume()
  • 暂停
sessionDownloadTask?.cancel(byProducingResumeData: { (resumeDataOrNil) in
            guard let resumeData = resumeDataOrNil else { return }
            self.resumeData = resumeData
})
  • 取消
sessionDownloadTask?.cancel()
  • 继续下载
guard let data = resumeData else { return }
let downloadTask = urlSession.downloadTask(withResumeData: data)
downloadTask.resume()
sessionDownloadTask = downloadTask
  • 代理
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        
        do {
            try FileManager.default.moveItem(atPath: location.path, toPath: savePath)
            print("下载完成")
        } catch {
            print("file error: \(error)")
        }
    }
    
    // 读取下载进度
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        
        if downloadTask == downloadTask {
            let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file) // 总大小 MB
            let downLoadedSize = ByteCountFormatter.string(fromByteCount: totalBytesWritten, countStyle: .file)
            let calculatedProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
            DispatchQueue.main.async {
                print("总大小: \(totalSize) , 已下载: \(downLoadedSize), 进度: \(calculatedProgress)")
                
            }
        }
    }
    
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        DispatchQueue.main.async {
            guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
            let backgroundCompletionHandler = appDelegate.backgroundCompletionHandler else { return }
            backgroundCompletionHandler()
        }
    }
  • AppDelegate
    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        backgroundCompletionHandler = completionHandler
    }