调用AfterdidCompleteWithError时如何使用URLSession downloadTaskWithResumeData重新开始下载..?

Posted

技术标签:

【中文标题】调用AfterdidCompleteWithError时如何使用URLSession downloadTaskWithResumeData重新开始下载..?【英文标题】:How to use URLSession downloadTaskWithResumeData to start download again when AfterdidCompleteWithError Called..? 【发布时间】:2018-04-08 15:24:18 【问题描述】:

我有从服务器下载两个文件并使用URLSession (let dataTask = defaultSession.downloadTask(with: url)) 将其存储到本地的代码。一切正常,唯一的问题是它正在下载第一个文件它给了我成功,但第二个文件没有完全下载..所以,我希望有一种方法可以重新下载第二个文件,它会给出错误..

我认为有办法做到这一点并开始研究它,我发现了这个委托方法..但没有太大帮助..如果失败,谁能帮我重新开始下载..我必须使用handleEventsForBackgroundURLSession 清除以前的下载..?

//当我获取文件名时将触发以下下载方法

  func download(path: String?, filenames: [String]) -> Int 
    for filename in filenames 
      var downloadFrom =  "ftp://" + username! + ":"
      downloadFrom += password!.addingPercentEncoding(withAllowedCharacters: .urlPasswordAllowed)! + "@" + address!

      if let downloadPort = port 
          downloadFrom += ":" + String(downloadPort) + "/"
       else 
        downloadFrom += "/"
      

      if let downloadPath = path  
        if !downloadPath.isEmpty 
          downloadFrom +=  downloadPath + "/"
        
      
      downloadFrom += filename

      if let url = URL(string: downloadFrom) 
        let dataTask = defaultSession.downloadTask(with: url)
        dataTask.resume()
      
    
    return DLResponseCode.success
  

请在下面找到委托方法..

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) 

    var responseCode = DLResponseCode.success

    // Move the file to a new URL
    let fileManager = FileManager.default
    let filename = downloadTask.originalRequest?.url?.lastPathComponent
    let destUrl = cacheURL.appendingPathComponent(filename!)
    do 

      let data = try Data(contentsOf: location)

      // Delete it if it exists first
      if fileManager.fileExists(atPath: destUrl.path) 
        do
          try fileManager.removeItem(at: destUrl)
         catch let error 
          danLogError("Clearing failed downloadFOTA file failed: \(error)")
          responseCode = DLResponseCode.datalogger.failToCreateRequestedProtocolPipe
        
      
      try data.write(to: destUrl)
     catch 
      danLogError("Issue saving data locally")
      responseCode = DLResponseCode.datalogger.noDataConnection
    


    // Complete the download message
    let message = DLBLEDataloggerChannel.Commands.download(responseCode: responseCode).description
    connectionManagerDelegate?.sendMessageToDatalogger(msg: message)

  

  func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 

    if error == nil 
        print("session \(session) download completed")
     else 
        print("session \(session) download failed with error \(String(describing: error?.localizedDescription))")


       // session.downloadTask(withResumeData: <#T##Data#>)
    
    guard error != nil else 
      return
    

    danLogError("Session \(session) invalid with error \(String(describing: error))\n")
    let responseCode = DLResponseCode.datalogger.failToCreateRequestedProtocolPipe
    let message = DLBLEDataloggerChannel.Commands.download(responseCode: responseCode).description
    connectionManagerDelegate?.sendMessageToDatalogger(msg: message)
  

// 当我调用 didWriteData 委托方法时,它在数据下方打印似乎没有下载完整的数据..

会话 <__nsurlsessionlocal:> 下载任务 <__nscflocaldownloadtask:> taskIdentifier: 2 running 在预期的 988980 字节中额外写入了 30028 字节(总共 988980 字节)。

//我为第二个文件收到的错误..这个错误有时会出现,但大多数时候会出现..

会话 <__nsurlsessionlocal:> 下载失败并出现错误 Optional("cancelled")

请帮我弄清楚..如果有什么方法可以在下载失败或失败后再次处理..

【问题讨论】:

向我们展示更多代码,否则您可能会得到冗长且可能充满假设的答案。如果这还不够糟糕,您可能会得到不考虑您的特定情况的替代解决方案。 我编辑并添加了代码.. 委托实现并不是特别有用。尽管它提供了您要做什么的基本概念,但向我们展示了您实际开始第一个下载任务的部分,然后是第二个失败的部分。为什么它会失败,你会得到什么错误? 我更新了问题请帮帮我.. 【参考方案1】:

如果请求是可恢复的,恢复数据应该在 NSError 对象的 userInfo 字典中。

不幸的是,Apple 似乎完全废弃了 NSURLSession 的编程指南(或者至少我在 Google 搜索结果中找不到),并且参考中的替换内容缺少 all 的讨论如何进行正确的错误处理的部分(即使您正在寻找的常量也丢失了),所以我将不得不在查看标题的帮助下从内存中描述它。艾克。

您要查找的密钥是NSURLSessionDownloadTaskResumeData

如果该键存在,它的值是一个小的 NSData blob。存储它,然后使用 Reachability API(使用该请求 URL 中的实际主机名)来决定何时重试请求。

在 Reachability 告诉您服务器可达后,使用恢复数据创建一个新的下载任务并启动它。

【讨论】:

关于它的文档现在在这里(至少在我发表评论时在这里):developer.apple.com/documentation/foundation/url_loading_system/… 感谢您的链接。

以上是关于调用AfterdidCompleteWithError时如何使用URLSession downloadTaskWithResumeData重新开始下载..?的主要内容,如果未能解决你的问题,请参考以下文章

java三种调用方式(同步调用/回调/异步调用)

LINUX系统调用

引用调用 vs 复制调用调用

RPC 调用和 HTTP 调用的区别

js方法调用

深入理解Java虚拟机——方法调用(解析调用)