Can't get the server response data while Using NSURLSession for background file upload

I am using NSURLSession for file upload and need to satisfy the following scenarios:

  • Large file uploads
  • Upload tasks should not be interrupted when the app is running in the background
  • After the file upload is completed, the server returns a JSON data to inform the app of some information.

When I debug with the my code attached below, I found that the

urlSession(_:task:didCompleteWithError:)

method is correctly called after the upload is completed,

BUT the

urlSession(_:dataTask:didReceive:)

method is never called.

Since I need to read the response data from the server after a successful file upload, if the urlSession(_:dataTask:didReceive:) method is not called, where should I get the server's response data from?

PS: When I change URLSessionConfiguration.background to let config = URLSessionConfiguration.default, I can create the upload task with URLSession.uploadTask(with: request, fromFile: fileURL, completionHandler:) and get the server response data in the completionHandler.

import Foundation

class FileUploader: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionDataDelegate {

public typealias ProgressHandler = (_ bytesSent: Int64, _ totalBytes: Int64) -> Void
public typealias CompletionHandler = (Error?, Data?) -> Void

private var session: URLSession!
private var responedData: Data?; // to hold data responsed from sever
private var progressHandler: ProgressHandler?
private var completionHandler: CompletionHandler?

override init() {
super.init()
let config = URLSessionConfiguration.background(withIdentifier: "com.example.LABackgroundSession")
session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
}

func upload(fileURL: URL, to url: URL) {
var request = URLRequest(url: url)
request.httpMethod = "POST"

let uploadTask = session.uploadTask(with: request, fromFile: fileURL)
uploadTask.resume()
}

// MARK: - URLSessionDataDelegate methods

public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
self.progressHandler?(totalBytesSent, totalBytesExpectedToSend);

}

//This method never called, and there is no other way i can get the response data.
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.responedData?.append(data);
}

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
self.completionHandler?(error, self.responedData)
} else {
self.completionHandler?(nil, self.responedData);
}
self.responedData = nil;
}
}

If the background session were going to give you body data back, the urlSession(_:dataTask:didReceive:) delegate method is the place where it’d show up.

I definitely remember this working. The background session wouldn’t deliver data as it came in, but would instead spool it to disk. Then, when the upload was finished, it’d deliver it to your delegate all in in one chunk.

What HTTP status code does the server return?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

the status code is 200

HTTP status code
the status code is 200

Hmmm, that rules out the only theory I had as to what might be causing this.

The behaviour you’re seeing seems like a bug to me, and I encourage you to file it as such. Please post your bug number, just for the record.

As to a workaround… let’s start with the basics: What platform are you seeing this on?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Can't get the server response data while Using NSURLSession for background file upload
 
 
Q