I have implemented a background upload task using URLSession as follow:
let boundary = UUID().uuidString
let configuration = URLSessionConfiguration.background(withIdentifier: "com.example.upload")
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: .main)
var urlRequest = URLRequest(url: URL(string: "https://server/file.php")!)
urlRequest.httpMethod = "POST"
urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var data = Data()
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"video\"; filename=\"rawvideo.mp4\"\r\n".data(using: .utf8)!)
data.append("Content-Type: video/mp4\r\n\r\n".data(using: .utf8)!)
data.append(videoData!)
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
let tempDir = FileManager.default.temporaryDirectory
let localURL = tempDir.appendingPathComponent("upload")
try? data.write(to: localURL)
session.uploadTask(with: urlRequest, fromFile: localURL).resume()
To handle the server response, I have used the following code [But I am not getting any print output. Seems this method is never called]
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
print("anoop")
guard let response = response as? HTTPURLResponse, (200...209).contains(response.statusCode) else {
DispatchQueue.main.async {
self.uploadComplete("Error", "Upload Server Down!")
}
print("error")
completionHandler(.cancel)
return
}
completionHandler(.allow)
}
To handle the server Data, I am using following code:
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if let toDictionary = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary {
print(toDictionary)
}
}
To handle the completion, I am using following code:
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
print(error.localizedDescription)
}
}
Additionally, I have a progress bar which I am updating as follows:
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
let uploadProgress:Float = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
let percent = Int(uploadProgress * 100)
DispatchQueue.main.async {
self.progressLabel.text = "\(percent)% completed"
self.progressView.setProgress(Float(uploadProgress), animated: true)
}
}
This code works well if the server is working fine [Response: 200]. But if I change the request URL to a dummy url like https://server/dummyfile.php, the progress bar still increments and I don't get any error since
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
doesn't work.
Is it possible that in case of server errors [404, 500] the progress bar doesn't increment?