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

How to use URLSession downloadTaskWithResumeData to start download again when AfterdidCompleteWithError Called..?

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

session <__NSURLSessionLocal: 0x103e37970> 下载任务 <__NSCFLocalDownloadTask: 0x108d2e​​e60>{ taskIdentifier: 2 } { 运行 } 从预期的 988980 字节。

//我正在获取第二个文件的错误..这个错误有时会出现,但并非总是如此..

会话 <__NSURLSessionLocal: 0x103e37970> 下载失败,错误可选("cancelled")

请帮我想想办法..如果有什么办法可以在下载失败后重新处理或者为什么失败..

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

不幸的是,Apple 似乎已经将 NSURLSession 的编程指南完全丢弃(或者至少我在 Google 搜索结果中找不到),以及替换内容缺少 all 讨论如何进行正确错误处理的部分(甚至缺少您要查找的常量),因此我将不得不对其进行描述在查看 headers 的帮助下,所有内容都来自记忆。恶心

您要查找的密钥是 NSURLSessionDownloadTaskResumeData

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

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