iOS通过URLSession进行多文件后台上传

  • 本文主要想解决的问题是,当你在前台点击上传文件,当用户进入到后台时你仍然想继续将文件上传完,而不是中断文件上传。如果你是打算直接在后台创建任务,那么会有延时的问题,当任务非常多的时候,靠后的任务延时将会非常严重(参考文章),因此这种情况也不在本文考虑范围内。

  • 后台上传需要创建后台session,需要通过一个标识符Identifier,如果你每次只需要上传一个文件,那么你可以创建一个全局的session,所有的文件都可以通过该session创建task上传,文件依次上传即可。如果你需要每次同时上传多个文件,那么可以根据你的需要创建多个session,但是session的Identifier必须不一样,否则运行过程当中会出错。以下代码可创建多个session

      //MARK: - 创建后台请求session
       func creatBackgroundSession(){
      
      let nowDate = Date()
      
      let dateFormatter = DateFormatter()
      dateFormatter.dateFormat = "YYYYMMddHHMMSS"
      let dateStr =  dateFormatter.string(from: nowDate)
      
      let randomNum = Int(arc4random()%10000)+1
      
      let configrationIdentifier =  "test" + dateStr + String(randomNum)
      
      
      let backgroundSessionConfigration = URLSessionConfiguration.background(withIdentifier: configrationIdentifier)
      //设置后台上传时的超时timeoutIntervalForResource,默认值为1周
      backgroundSessionConfigration.timeoutIntervalForResource = 24*60*60
      backgroundSession = URLSession(configuration: backgroundSessionConfigration, delegate: self, delegateQueue: OperationQueue.main)
    
      
      }
    
  • 创建上传的task,urlsession后台上传一定是文件流的形式,而不是数据流的形式,因此除了前端需要注意还应当与后台进行沟通,让他们以接受文件流的形式存储收到的流。

     var request = URLRequest(url: URL(string: url )!)
     request.httpMethod = "POST"
     let contentType = "multipart/form-data; boundary=\(XYboundary)"
     request.setValue(contentType, forHTTPHeaderField: "Content-Type")
     request.addValue("text/html,application/json,text/json", forHTTPHeaderField: "Accept")
     //创建上传的
     let backgroundTask = backgroundSession.uploadTask(with: request, fromFile:  URL(fileURLWithPath: filePath))
     // 开始下载
     backgroundTask.resume()
    
  • 需要实现URLSessionDelegate,URLSessionTaskDelegate,URLSessionDataDelegate等代理方法

      func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
      //对进度进行监控
      } 
      
      
      func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
      //用来接收上传完成后后台返回的数据
      }
      
          //MARK: - 上传结束操作,不管是否成功都会调用
      func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
      //用来处理上传结束流程
      }
      
          //MARK: - 后台上传完执行代理方法
       func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
       //如果是在后台上传的还会调用这个方法
      }
    
  • 当然,在AppDelegate中你还得实现如下方法

      //MARK: - 后台下载上传完成处理
      func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
          
      }
    
  • 如果你想停止上传,那么可以通过如下两种方式结束这个session

    1. backgroundSession.finishTasksAndInvalidate(),这个方法会在完成已开启的task后,结束这个session
    2. backgroundSession.invalidateAndCancel(),该方法是立即停止task并结束session
  • 这里有一个完整的Demo,参考Demo相信你可以加深理解,如果对你有帮助,给个Star,让更多人可以得到帮助。Demo在这里

  • 本文谢绝转载,如需转载请联系我授权,原创不易,还请理解

你可能感兴趣的:(iOS通过URLSession进行多文件后台上传)