我有一个API,可以生成签名的下载链接,该链接会在很短的时间后过期。我想添加恢复下载的功能,但是如果资产的URL发生变化,则URLSession API不提供恢复下载的本机功能。
我尝试解决此问题的方法是跟踪暂停时下载的字节数,存储下载的数据blob,获取新签名的下载URL,使用Range标头继续下载,然后将所有数据blob连接在一起下载完成。
以下是用于开始下载的代码:
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: signedURL)
self.sessionDownloadRequest = task
我面临的问题是,恢复数据var似乎并未实际包含已下载的数据。
self.sessionDownloadRequest.cancel(byProducingResumeData: { (data) in
print(data.count) //This surprisingly always returns the same count
}
看起来,无论我在暂停之前继续下载多长时间,该数据blob的大小始终是相同的。在哪里/如何访问已下载的数据块?
谢谢!
答案 0 :(得分:1)
由以下方式返回的简历数据:
$sql = "INSERT INTO $mytable (number, name, description)
VALUES (" . $_POST['number'] . ","
. $_POST['name'] . ","
. $_POST['description'] . ")";
实际上是一个包括:
的plist您可以使用以下代码访问plist:
- (void)cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler;
您实际上并不需要像最初建议的那样存储和连接数据blob。您可以使用更新的签名URL替换存储在plist(NSURLSessionResumeCurrentRequest)中的当前请求。在此之后,创建一个新的resumeData实例来代替原始实例。
if let resumeDictionary = try? PropertyListSerialization.propertyList(from: self, options: PropertyListSerialization.MutabilityOptions.mutableContainersAndLeaves, format: nil), let plist = resumeDictionary as? [String: Any] {
print(plist)
}
从那里你可以操纵plist并实际创建一个新的plist,直到实例方法:
guard let bytesReceived = plist["NSURLSessionResumeBytesReceived"] as? Int
else {
return nil
}
let headers = ["Range":"bytes=\(bytesReceived)"]
let newReq = try! URLRequest(url: signedURL, method: .get, headers: headers)
let archivedData = NSKeyedArchiver.archivedData(withRootObject: newReq)
if let updatedResumeData = try? PropertyListSerialization.data(fromPropertyList: plist, format: PropertyListSerialization.PropertyListFormat.binary, options: 0) {
return updatedResumeData
}
注意:如果您使用的是iOS 10和macOS10.12。*,则会出现一个错误,导致恢复功能无法正常工作,因为plist已损坏。查看本文以获得修复。在访问plist之前,您可能需要修复plist。 Resume NSUrlSession on iOS10