2017-09-17 31 views
-2

我有一个API可以生成签名的下载链接,并在短时间内过期。我想添加恢复下载的功能,但如果资源的URL发生更改,则URLSession API不会提供恢复下载的本机功能。当下载URL更改时恢复下载

我试图解决这个问题的方法是跟踪暂停时下载的字节数,存储下载的数据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

你还没有显示任何相关的代码,所以谁知道你在做什么,对或错? – matt

+0

@matt,我添加了最初的请求代码。只是为了澄清,我没有遇到任何问题,例如获取新的已签名URL,恢复具有特定范围的下载或数据blob的连接,所以我没有包含这些代码以保持问题的简洁。如果您还有其他想看的东西,请告诉我。 – neilb

回答

1

由返回的恢复数据:

- (void)cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler; 

实际上是包括的plist:

  • NSURLSessionDownloadURL
  • NSURLSessionResumeBytesReceived
  • NSURLSessionResumeCurrentRequest
  • NSURLSessionResumeEntityTag
  • NSURLSessionResumeInfoTempFileName
  • NSURLSessionResumeInfoVersion
  • NSURLSessionResumeOriginalRequest
  • NSURLSessionResumeServerDownloadDate

您可以用下面的代码访问的plist:

if let resumeDictionary = try? PropertyListSerialization.propertyList(from: self, options: PropertyListSerialization.MutabilityOptions.mutableContainersAndLeaves, format: nil), let plist = resumeDictionary as? [String: Any] { 
     print(plist) 
} 

你实际上并不需要存储和连接的数据你最初建议的斑点。您可以使用更新后的签名URL替换存储在plist(NSURLSessionResumeCurrentRequest)中的当前请求。在此之后,创建一个新的resumeData实例来使用,而不是原来的。

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 
} 

从那里,你可以操纵的plist和实际创建一个新的将它传递给直通实例方法:

- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData; 

注:如果您使用iOS的10 macOS10.12工作。 *,有一个错误,防止恢复能力工作,因为plist损坏。检查这篇文章了解修复。在访问某些属性之前,您可能需要修复plist。 Resume NSUrlSession on iOS10