当调用AfterdidCompleteWithError时,如何使用URLSession downloadTaskWithResumeData再次开始下载..?

时间:2018-04-08 15:24:18

标签: objective-c swift nsurlsession nsurlsessiondownloadtask nsurlsessiondatatask

我有代码从服务器下载两个文件,并使用URLSessionlet 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委托方法时,它在数据下方打印似乎没有下载完整的数据..

会话&lt; __ NSURLSessionLocal:0x103e37970&gt;下载任务&lt; __ NSCFLocalDownloadTask:0x108d2e​​e60&gt; {taskIdentifier:2} {running}在预期的988980字节中写入了额外的30028字节(总共988980字节)。

//我得到第二个文件的错误..这个错误有时候并不总是,但大部分时间都是..

会话&lt; __ NSURLSessionLocal:0x103e37970&gt;下载失败,错误可选(“已取消”)

请帮我搞清楚..如果有任何办法在失败后再次处理下载或为什么失败..

1 个答案:

答案 0 :(得分:0)

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

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

您要找的关键是NSURLSessionDownloadTaskResumeData

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

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