
本文共 6318 字,大约阅读时间需要 21 分钟。
内容来自学习等系列课程,记录学习笔记
Networking with URLSession二 上传&下载
下载和上传Task
URLSessionDownloadTask
直接把服务器的响应写入到一个临时文件中,并提供进度更新。如果在background session中使用download task,即使app程序被暂停或未运行,这些下载也会继续下载。
URLSession
创建download task的方式
func downloadTask(with: URL,completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void)func downloadTask(with: URLRequest,completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void)
downloadTask把数据保存在一个临时的文件中,所以在completion handler返回之前,必须读取和处理文件,或者把文件copy到一个永久的位置。否则文件会被删除,data会丢失。
func downloadTask(with: URL)func downloadTask(with: URLRequest)
在调用过程中:
- session会周期性的调用代理方法,提供一些状态信息
- 在成功时调用方法或者一个completion回调。在这个方法中,你要么打开这个文件来读取,要么把这个文件移动到沙盒中的一个永久的位置
- 失败时调用方法或者一个completion回调
一个download task如果在完成之前被取消或者下载失败,可以保存resume data,并继续下载。
func cancel(byProducingResumeData:@escaping (Data?) -> Void)func downloadTask(withResumeData: Data,completionHandler: @escaping (URL?,URLResponse?, Error?) -> Void)func downloadTask(withResumeData: Data)
与、不同,NSURLSessionDownloadTask
通过HTTP状态码,把服务器错误,报告给响应的NSError
对象:
Server-side errors | NSErrors |
---|---|
401 Unauthorized | NSURLErrorUserAuthenticationRequired |
403 Forbidden | NSURLErrorNoPermissionsToReadFile |
407 Proxy Authentication Required | NSURLErrorUserAuthenticationRequired |
Other | NSURLErrorFileDoesNotExist |
URLSessionUploadTask
与download task类似。可直接通过completionHandler来处理结果,而不通过代理
如下,上传data数据:
func uploadTask(with: URLRequest, from: Data?,completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void)func uploadTask(with: URLRequest, from: Data)
但是不能直接使用URL来创建upload task,需要通过URLRequest来创建。因为upload task的http请求,需要http body。
除了上传data数据外,还可以上传file:
func uploadTask(with: URLRequest, fromFile: URL,completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void)func uploadTask(with: URLRequest, fromFile: URL)
另外还有一个stream request
func uploadTask(withStreamedRequest: URLRequest)
各种优先级
1.URLSessionConfiguration
的networkServiceType
属性对标准的网络流量,网络电话,语音,视频,以及由一个后台进程使用的流量进行了区分。值可为default, voip, video, background, voice
URLSessionTask
的priority
属性。即你希望host处理任务的相对优先级。0.0 (lowest)
到 1.0 (highest)
, default
是0.5 3.URLRequest
的networkServiceType
。可重写配置对象的networkServiceType
4.URLSession’s delegateQueue
qualityOfService: userInteractive, userInitiated, utility, background 缓存
大量的下载可以很好的利用缓存来减少网络拥堵的问题。Default configuration使用的是一个持久的基于disc的cache。
cache会减少app对网络连接的依赖,提高的app的性能。 默认的cache policy使用的是protocol的cache policy,而protocol通常是HTTP。参考文档:
下载
本例下载,是下载音频示例,如:
http://audio.itunes.apple.com/apple-assets-us-std-000001/AudioPreview30/v4/02/4e/35/024e3534-92b4-6e6d-217e-b5714b6faa20/mzaf_5572571419358472776.plus.aac.p.m4a
开始下载资源
代码如下:func startDownload(_ track: Track) { let download = Download(url: track.previewURL) //下载任务 download.task = defaultSession.downloadTask(with: track.previewURL) { location, response, error in self.saveDownload(download: download, location: location, response: response, error: error) } download.task!.resume() download.isDownloading = true activeDownloads[download.url] = download } func saveDownload(download : Download, location : URL?, response : URLResponse?, error : Error?) { let sourceURL = download.url if error != nil { return } activeDownloads[sourceURL] = nil //copy目的地地址 let destinationURL = localFilePath(for: sourceURL) //先移除在复制 let fileManager = FileManager.default try? fileManager.removeItem(at: destinationURL) do { try fileManager.copyItem(at: location!, to: destinationURL) } catch let error { print("Could not copy file to disk: \(error.localizedDescription)") } //更新UI if let index = trackIndex(for: download.task!) { DispatchQueue.main.async { self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none) } } }
暂停下载
//暂停下载 func pauseDownload(_ track: Track) { guard let download = activeDownloads[track.previewURL] else { return } //处理已下载的数据 download.task!.cancel(byProducingResumeData: { (data) in download.resumeData = data }) download.isDownloading = false //更新UI if let index = trackIndex(for: download.task!) { DispatchQueue.main.async { self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none) } } }
取消下载
//取消下载 func cancelDownload(_ track: Track) { guard let download = activeDownloads[track.previewURL] else { return } //取消下载 download.task!.cancel() download.isDownloading = false activeDownloads[track.previewURL] = nil if let index = trackIndex(for: download.task!) { DispatchQueue.main.async { self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none) } } }
继续下载
// 继续下载 func resumeDownload(_ track: Track) { guard let download = activeDownloads[track.previewURL] else { return } if let resumeData = download.resumeData { //在原来的数据上继续下载 download.task = defaultSession.downloadTask(withResumeData: resumeData, completionHandler: { (location, response, error) in self.saveDownload(download: download, location: location, response: response, error: error) }) }else { //重新下载 download.task = defaultSession.downloadTask(with: download.url, completionHandler: { (location, response, error) in self.saveDownload(download: download, location: location, response: response, error: error) }) } download.task!.resume() download.isDownloading = true if let index = trackIndex(for: download.task!) { DispatchQueue.main.async { self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none) } } }
上传
上传以上一节的PostRouter
为例,上传json数据
let session = URLSession(configuration: .ephemeral)let putRequest = PostRouter.update(1, ["author": "Part 6", "title": "Upload Task"]).asURLRequest()typealias JSONDictionary = [String: Any]let putTask = session.uploadTask(with: putRequest, from: putRequest.httpBody) { data, response, error in defer { PlaygroundPage.current.finishExecution() } guard let data = data, let response = response as? HTTPURLResponse, response.statusCode == 200 else { print("No data or statusCode not OK") return } var jsonResult: JSONDictionary do { let result = try JSONSerialization.jsonObject(with: data, options: []) jsonResult = result as! JSONDictionary } catch { print(error.localizedDescription) return }}putTask.resume()
其它文档
转载地址:https://windzen.blog.csdn.net/article/details/70308367 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关于作者
