【问题标题】:How to use URLSession downloadTaskWithResumeData to start download again when AfterdidCompleteWithError Called..?调用AfterdidCompleteWithError时如何使用URLSession downloadTaskWithResumeData重新开始下载..?
【发布时间】: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")

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

【问题讨论】:

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

标签: objective-c swift nsurlsession nsurlsessiondownloadtask nsurlsessiondatatask


【解决方案1】:

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

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

您要查找的密钥是NSURLSessionDownloadTaskResumeData

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

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-04-15
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多