ios - 后台上传在 Swift 中不起作用

标签 ios swift urlsession background-fetch

我正在尝试实现一个代码,其中将在文件上传到 AWS 服务器后不久调用 API,但它必须处于后台模式。虽然 AWS sdk 在后台模式下管理将文件上传到他们的服务器,但以下代码不起作用。

ViewController.swift

func upload(_ mediaData:Data){

   //AWS method to upload a file
   AWSS3UploadImageData(mediaData!, strImageName: "person.jpg", strContentType: "img/*", { (isSuccess, result, strMessage) in
         if isSuccess {
              let arrPost = result as! [[String : String]]

              //Call custom webservice
              VaultUploadWebService.shared.callVaultUploadWebService(Params: arrPost)
         }
         else {
             print("Unsuccess")
         }
   })
}

VaultWebService.swift

class VaultUploadWebService: NSObject {

    static let shared = VaultUploadWebService()

    var savedCompletionHandler: (() -> Void)?

    func callVaultUploadWebService(Params: [[String : String]]) {

        startRequest(for: "www.example.com", param: Params)
    }


    func startRequest (for urlString: String, param: [[String : String]]) {

        let identifier = "com.com.background" + "\(NSDate().timeIntervalSince1970 * 1000)"
        let configuration = URLSessionConfiguration.background(withIdentifier:identifier)
        let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)

        let url = URL(string: urlString)!
        var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 180)
        request.httpMethod = "post"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")      
        do {
           let paramsData = try JSONSerialization.data(withJSONObject:param, options:[])
           request.httpBody =  paramsData

           session.uploadTask(withStreamedRequest: request).resume()
       }catch {
        print("JSON serialization failed: ", error)
        return
       }


        //Also tried using the following but no luck
        /*guard let documentDirectoryUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
        let fileUrl = documentDirectoryUrl.appendingPathComponent("Persons.json")
        let jsonEncoder = JSONEncoder()
        do {
          let jsonData = try jsonEncoder.encode(param)
          try jsonData.write(to: fileUrl, options: [])
        }
        catch let error {
          print(error.localizedDescription)
        }
        session.uploadTask(with: request, fromFile: fileUrl).resume()*/

    }

}


extension VaultUploadWebService: URLSessionDelegate {
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        DispatchQueue.main.async {
            self.savedCompletionHandler?()
            self.savedCompletionHandler = nil
        }
    }
}

extension VaultUploadWebService: URLSessionTaskDelegate{

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

        if (error != nil){
            print(error?.localizedDescription ?? "error")
        }
        else{
            print(task.response)
        }
    }
}

最后.. Appdelegate.swift

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {

   let id = identifier as NSString
   if id.contains("com.amazonaws") {
       AWSS3TransferUtility.interceptApplication(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)
   }else{
       VaultUploadWebService.shared.savedCompletionHandler = completionHandler
   }
}

但是这个委托(delegate)方法永远不会被调用,而它被调用用于 AWS 上传。我认为这是后台 uploadTask 对我不起作用的主要原因。卡了2天。任何帮助将不胜感激。

最佳答案

如果您通过 uploadTask(withStreamedRequest:) 创建上传任务,

httpBody 将被忽略。它需要实现 urlSession(_:task:needNewBodyStream:) 委托(delegate)回调。对于背景模式,它不适合。尝试使用 uploadTask(with request: URLRequest, from bodyData: Data) 代替。此外,它看起来像 VaultUploadWebService 没有对 session 对象的任何引用。尝试将 session 存储为 VaultUploadWebService 的成员。

关于ios - 后台上传在 Swift 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51709220/

相关文章:

swift - 如何为仅适用于 Swift 4.1 中的可选泛型参数的泛型结构创建扩展?

ios - 为什么我无法在嵌套调用尝试中创建 url

ios - NSDate - 添加天数不会改变年份值

ios - 在 uiscrollview 中检测 toucesbegin

ios - 如何从 UIAlertViewController 的处理程序正确打开 URL?

ios - 保持导航 Controller 的状态,只改变 View

ios URLSessionDataTask 使用数据恢复

swift - 带 DispatchGroup 的并行 URLSession 请求在 1 个请求上调用完成处理程序两次

ios - 自定义 UISlider 无法正确设置最小轨道颜色

ios - graph.facebook.com 的 DNS 问题