使用swift中的session.uploadTask上传失败如何检查错误?

How to check error if uploading is failed using session.uploadTask in swift?

我正在后台上传视频文件,但我不知道如何检查视频文件是否上传失败。我正在使用 URLSession 上传文件。如果有人有想法请帮助我。

private func uploadMediaWith(mediaURL: URL, mediaMimeType: MediaMimeType, AWSPresignedURL: URL) {
    let finalMediaURL = mediaURL.updatedSandboxURL()
    Log.echo(key: "\(self.KEY)", text: "setup upload for \(mediaURL.lastPathComponent)")
    let url = AWSPresignedURL // https://dentiscope-development.s3.us-west-2.amazonaws.com/exams/42/videos/BottomLeftOutside-b121986d-bd5c-4b6f-bed2-f030978f03f0.mp4?x-amz-acl=private&x-amz-meta-exam_id=42&x-amz-meta-uuid=b121986d-bd5c-4b6f-bed2-f030978f03f0&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5WF3XEUH4WAYWLEI%2F20211115%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20211115T070402Z&X-Amz-SignedHeaders=host%3Bx-amz-acl%3Bx-amz-meta-exam_id%3Bx-amz-meta-uuid&X-Amz-Expires=432000&X-Amz-Signature=a6ede8cd558cd1df5c5d6e62be1237f995b7ac97e235112acc263e3b0de1531f
    let boundary = UUID().uuidString
    var request = URLRequest(url: url)
    request.httpMethod = "PUT"
    
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    if let authToken = SignedUserInfo.sharedInstance?.authToken {
      request.setValue("Authorization", forHTTPHeaderField: "Bearer " + authToken)
    }
    
    let config = URLSessionConfiguration.background(withIdentifier: boundary)
    config.waitsForConnectivity = true
    config.shouldUseExtendedBackgroundIdleMode = true
//    config.httpMaximumConnectionsPerHost = 4
//    config.networkServiceType = .background
    
    let session = URLSession(configuration: config, delegate: self, delegateQueue: .main)
    
    var data = Data()
    if(mediaMimeType == MediaMimeType.video) {
      do {
        let videoData = try Data(contentsOf: finalMediaURL)
        data.append(videoData)
      } catch {
        Log.echo(key: "MediaMimeType.video", text: error.localizedDescription)
        fatalError("\(self.KEY) COULD NOT GET DATA OF THE VIDEO || \(finalMediaURL.lastPathComponent)")
      }
    }
    
    request.httpBody = data
    DispatchQueue.global().async {
      let task = session.uploadTask(withStreamedRequest: request)
      // how to check if failled to uload
      self.uploadingURL = finalMediaURL
      task.resume()
      Log.echo(key: "\(self.KEY)", text: "execute upload for \(mediaURL.lastPathComponent) || session id \(boundary)")
    }
  }

如果我使用此代码:

let task = session.dataTask(with: request) { (data, urlResp, error) in
        if let error = error {
          print(error)
        }
      } //uploadTask(withStreamedRequest: request)
      self.uploadingURL = finalMediaURL
      task.resume()

然后出现此错误: 由于未捕获的异常 'NSGenericException' 而终止应用程序,原因:'Completion handler blocks are not supported in background sessions. Use a delegate instead.' 以 NSException

类型的未捕获异常终止

使用委托并将其转换为完成块,您可以使用如下内容:

class UploadContainer: NSObject, URLSessionTaskDelegate {
    
    let session: URLSession
    let request: URLRequest
    
    private var completion: ((_ error: Error?) -> Void)?
    private var task: URLSessionUploadTask?
    
    private var selfRetain: Any? // This is to persist lifetime of this class for the duration of request execution
    
    init(request: URLRequest, session: URLSession = .shared, completion: @escaping ((_ error: Error?) -> Void)) {
        self.request = request
        self.session = session
        self.completion = completion
        super.init()
        self.upload()
    }
    
    private func upload() {
        let task = session.uploadTask(withStreamedRequest: self.request)
        self.task = task
        task.delegate = self
        self.selfRetain = self
        task.resume()
    }
    
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        self.selfRetain = nil
        completion?(error)
        completion = nil
    }
    
}

然后当您生成请求时,您只需调用

UploadContainer(request: request) { error in
    if let error = error {
        print("Error occurred uploading file \(error)")
    } else {
        print("File was successfully uploaded")
    }
}

但是有很多方法可以实现这一点。重点是一旦你创建了一个任务,你需要分配一个委托。在提供的代码中,您可以看到这一行 task.delegate = self。无论谁被指定为委托人(在本例中 selfUploadContainer)都需要实现由 : NSObject, URLSessionTaskDelegate 完成的委托。 class 现在可以实现 URLSessionTaskDelegate 中记录的一些方法。但是我们只对完成上传感兴趣(有或没有错误)这似乎是一种名为func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)的方法。我希望这对你有用。