今天在使用URLSessionDownloadTask实现断点续传功能时发现在暂停时始终拿不到resumeData数据,导致无法实现断点续传。
使用cancel方法data始终为nil
task?.cancel(byProducingResumeData: { (data) in
})
从头检查了很多遍,没有任何问题,最后通过查阅官方文档,终于发现了问题所在。
文档中准确描述了response的header中需要包括ETag or Last-Modified,我们后台提供的下载链接的header中并没有包含这两个字段,加上后断点续传就成功了。
为什么需要加入这两个字段呢?
Last-Modified
客户端在第一次请求某个URL成功后,服务器返回的response中会包含Last-Modified,用来表示服务器资源最后一次被修改的时间,格式如下
Last-Modified: Wed, 23 Mar 2022 16:35:58 GMT
当第二次访问这个URL后,客户端会在header中传入If-Modified-Since,用来询问服务器这个时间之后是否有过修改,格式如下
If-Modified-Since: Wed, 23 Mar 2022 16:35:58 GMT
如果没有修改,则服务器会返回304,告诉客户端没有修改,则客户端可以使用缓存数据,如果有修改,则服务器会返回新的数据。
ETag
ETag在HTTP 协议规格的定义为“被请求变量的实体值”。ETag表示资源标识是否有变更,而Last-Modified更倾向于时间状态。
ETag:"623b4c6e-1+8e4947"
ETag一般是文件内容的hash值生成的,当文件内容发生变化,ETag也会发生变化,由于Last-Modified最小时间是秒,所以可能在数据变化很快的情况下,Last-Modified会有不准确的缺点。这是使用ETag就要比Last-Modified用更加准确。(事实上,很多时候会将这两个一起使用)
和Last-Modified相似,在第一次请求拿到ETag后,客户端会在第二次访问服务器时在header中传入If-None-Match将ETag返回给服务器,如果相等,服务器也会返回304,不相等则返回新的数据。