猫猫分享,必须精品

原创文章,欢迎转载。转载请注明:翟乃玉的博客
地址:http://write.blog.csdn.net/postlist

下载-断点续传

通过URLSession进行下载,通过OutputStream写入文件,通过URLSessionDataTask来控制下载的继续暂停取消等操作

一:下载过程

1:一次完整的下载流程

1:创建request,session

//request
var request = URLRequest(url: url, cachePolicy:URLRequest.CachePolicy.reloadIgnoringLocalCacheData,
timeoutInterval: 0)//session
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)

2:设置下载偏移量 :offset

request.setValue(String(format: "bytes=%lld-", offset), forHTTPHeaderField: "Range")

3:根据request从会话session中拿到URLSessionDataTask任务,并且继续执行

self.dataTask = self.session.dataTask(with: request)
self.dataTask?.resume()

4:通过session的代理方法,进行数据的传输下载

///主要用到了三个代理方法/// 第一次接受到相应的时候调用(响应头, 并没有具体的资源内容)/// 通过这个方法里面系统提供的回调代码块(completionHandler) 可以控制:是继续请求, 还是取消本次请求func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void);/// 当用户确定, 继续接受数据的时候调用func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data);/// 请求完成时候调用func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?);

4.1第一次接受到相应的时候,保存要下载资源的大小,然后打开输出流,开始下载数据

//创建输出流
let outputStream = OutputStream(toFileAtPath: self.tmpFilePath, append: true)
//打开输出流
outputStream.open()
//开始下载数据
completionHandler(.allow)

如果出现异常,name就取消本次请求,重新开始下载操作

//取消本次请求
completionHandler(.cancel)
//重新开始下载操作
self.downLoad()

4.2当用户确定, 继续接受数据的时候,往输出流中写数据,以及一些其他操作像:进行下载进度,下载速度的计算

// 往输出流中写入数据
data.withUnsafeBytes({ (p: UnsafePointer<UInt8>) -> Void inoutputStream.write(p, maxLength: data.count)
})
//进行下载进度,下载速度的计算
tmpSize += Int64(data.count)
//计算一秒中的速度
downTask.totalRead += Int64(data.count);
let currentDate = Date()
let time = currentDate.timeIntervalSince(downTask.lastDate)
//当前时间和上一秒时间做对比,大于等于一秒就去计算
if  time >= 1 {//计算速度let speed = Double(downTask.totalRead) / time//把速度转成KB或MdownTask.speed = speed//维护变量,将计算过的清零downTask.totalRead = 0//维护变量,记录这次计算的时间downTask.lastDate = currentDateNYLog("------speed : \(speed)")
}// 记录进度
self.progress = 1.0 * Double(tmpSize) / Double(totalSize)
// 每隔downLoaderConfig.progressMinReturn 秒 闭包返回一次进度
if currentDate.timeIntervalSince(progressLastDate) > downLoaderConfig.progressMinReturn {self.progressClosure(self.progress,tmpSize,totalSize)progressLastDate = currentDate
}

4.3请求完成时候,成功后移动文件,关闭输出流,清理会话资源

2:细节:

  1. 下载时候用到两个路径:缓存路径,临时缓存路径
  2. 下载的时候,将数据写入到临时缓存路径当中
  3. 下载完成,将临时缓存路径中下载好的文件移动到缓存路径中
  4. 如果缓存路径里面有url对应的下载文件,那就说明已经下载完成了
  5. 临时缓存是否下载完成, 通过对下载的文件大小和知道的文件大小做对比实现

3:下载文件大小的获取

文件的大小可以通过响应头(response)的Content-Length (或者Content-Range)或者服务器给相应的字段来获取设置.

坑:在续传的时候响应头(response)的Content-Length是变化的, 于是在第一次拿到content-length的时候根据url用UserDefaults进行了一次缓存,然后直接用.

ps:(这个地方可以让后台服务器给,还有的做法会给一个文件的md5,如果能有文件的md5就不需要考虑url是否更改了之类的,当然这些属于业务逻辑上的了,具体还需要根据自己的业务来进行分析)

二:断点续传原理

1:原理

断点续传的工作机制,在HTTP请求头中,有一个Range的关键字,通过这个关键字可以告诉服务器返回哪些数据。
比如:
bytes=500-999 表示第500-第999字节
bytes=500- 表示从第500字节往后的所有字节
然后再根据服务器返回的数据,将得到的data数据拼接到文件后面,就可以实现断点续传了。

2:暂停和续传

暂停和续传网上很多都是运用了resumedata来获取已经下载的信息,但是在ios10 中需要做一些特殊处理, 这里我没有用这种方式,而是通过直接拿到本地已经下载的临时文件的大小,来作为对下一次数据的请求

Ps: 这里有一个神坑

FileManager.default.attributesOfFileSystem(forPath: )
FileManager.default.attributesOfItem(atPath: )

两个方法返回的都是[FileAttributeKey: Any] 的字典,并且第一个方法有file关键字,理所当然以为是用第一个,但真的应该用第二个

三:其他

关于NSURLSession的一些知识可以看这篇文章
iOS中利用NSURLSession进行文件断点下载

下载地址:https://github.com/znycat/NYDownLoadLib.git

猫猫学Swift之下载-断点续传相关推荐

  1. OC/Swift 技术 下载文件(断点续传 AFN下载文件 Alamofire下载文件 原生下载)(源码)

    一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹.靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希 ...

  2. 猫猫学IOS(四)UI之半小时搞定Tom猫

    话不多说 先上效果 项目源码素材下载地址: Tom猫游戏代码iOS 素材http://blog.csdn.net/u013357243/article/details/44457357 效果图 曾经风 ...

  3. (素材源代码)猫猫学IOS(四)UI之半小时搞定Tom猫

    下载地址:http://download.csdn.net/detail/u013357243/8514915 以下是执行图片展示 制作思路以及代码解析 猫猫学IOS(四)UI之半小时搞定Tom猫这里 ...

  4. 猫猫学IOS(六)UI之iOS热门游戏_超级猜图

    猫猫分享,必须精品 素材地址:http://blog.csdn.net/u013357243/article/details/44539069 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:ht ...

  5. 关东升的《从零开始学Swift》即将出版

    大家好: 苹果2015WWDC大会发布了Swift2.0,它较之前的版本Swift1.x有很大的变化,所以我即将出版<从零开始学Swift><从零开始学Swift>将在< ...

  6. (素材源码) 猫猫学IOS(五)UI之360等下载管理器九宫格UI

    猫猫分享,必须精品 先看效果 代码学习地址: 猫猫学IOS(五)UI之360等下载管理器九宫格UI 猫猫学IOS(五)UI之360等下载管理器九宫格UI http://blog.csdn.net/u0 ...

  7. 学Java需要下载什么软件?都有什么作用?

    学习java并非大家想象中的那么简单,除了书本和老师面授,软件的使用也有很大的作用,接下来小编为大家分享的就是关于"学Java需要下载什么软件?都有什么作用?"的内容,希望能够给正 ...

  8. 关东升的《从零开始学Swift》3月9日已经上架

    大家一直期盼的<从零开始学Swift>于3月9日已经上架,它是关东升老师历时8个月的呕心沥血所编著,全书600多页,此本书基于Swift 2.x,通过大量案例全面介绍苹果平台的应用开发.全 ...

  9. 使用OKHttp3实现下载(断点续传、显示进度)

    2019独角兽企业重金招聘Python工程师标准>>> OKHttp3 是如今非常流行的 Android 网络请求框架,那么如何利用 Android 实现断点续传呢,今天写了个 De ...

最新文章

  1. [文档].JLINK挂了怎么办?自己修![转载].JLINK_V8固件烧录和固件升级指导.pdf
  2. html标签的id中带有.号的获取方式
  3. Android之View的绘制流程解析
  4. VMware Vix API 操作虚拟机
  5. ant 实现批量打包android应用
  6. 一张图看懂单机/集群/热备/磁盘阵列(RAID)
  7. 啥?这就是一个高级报表/BI数据分析工程师的一天?
  8. C++11 强类型枚举
  9. 编写一个Applet在屏幕上画椭圆,椭圆的大小和位置由鼠标决定
  10. mysql异构迁移_如何利用数据异构实现多级缓存和数据迁移
  11. Python基础总结
  12. 如何将虚拟机上的文件复制到主机上
  13. python爬虫作业帮_2020高校邦《网络数据采集与Python爬虫【带实验】》课后作业参考答案2020知到《PPT创意动画》单选题答案...
  14. 高速公路车路协同创新示范情况全扫描(2021版)
  15. Google Earth Engine简介
  16. 计算机桌面图标如何变小,电脑屏幕图标怎么变小_桌面图标太大怎么调小
  17. 百度Apollo的dreamview的frontend的数据传输部分简单梳理
  18. YOLOV5源码解读(数据集加载和增强)
  19. 自由传奇|为你的队伍加油!
  20. python输入素数为什么要先判断是否是素数再用欧拉筛法

热门文章

  1. DeepRapper 代码详解
  2. 三菱PLC ALTP指令
  3. python 编程开发 —— 字典(dict)介绍
  4. OpenGL核心技术之HDR
  5. 字节跳动第四批笔试题
  6. 第十四届中国大学生服务外包创新创业大赛百度赛道-智慧医疗赛题baselin
  7. 解决在PE里遇到的问题
  8. 通过硬件ID精确寻找驱动--摄像头ID篇
  9. 原油进口将达1.3亿吨 涨价使中国多付百亿美元
  10. MySQL数据迁移工具