美文网首页锻炼吃饭的家伙网络
iOS通过URLSession进行多文件后台上传

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

作者: xiaoyi6409 | 来源:发表于2017-09-11 16:14 被阅读516次
    • 本文主要想解决的问题是,当你在前台点击上传文件,当用户进入到后台时你仍然想继续将文件上传完,而不是中断文件上传。如果你是打算直接在后台创建任务,那么会有延时的问题,当任务非常多的时候,靠后的任务延时将会非常严重(参考文章),因此这种情况也不在本文考虑范围内。

    • 后台上传需要创建后台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在这里

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

    相关文章

      网友评论

      • 690a597c0ae8:请教楼主 可否分享一下服务器端的代码
      • PGOne爱吃饺子:楼主 上传多个文件没必要创建多个sesssion吧,一个session可以开启多个task的啊,没有必要创建多个session吧

      本文标题:iOS通过URLSession进行多文件后台上传

      本文链接:https://www.haomeiwen.com/subject/vwjfsxtx.html