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;
}
}