skip to Main Content

I am using URLSessionConfiguration.background and uploadTask to upload a file from an iOS app.

The upload session is configured in the following way:

let configuration = URLSessionConfiguration.background(withIdentifier: "com.mycompany.myapp.fileUploader")
configuration.isDiscretionary = false
configuration.allowsCellularAccess = true
uploadURLSession = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)

and the request is:

request.httpMethod = "POST"
request.setValue("application/octect-stream", forHTTPHeaderField: "Content-Type")


let task = uploadURLSession.uploadTask(with: request, fromFile: fileURL)

I’d like to understand how to manage the error handling.

How the http errors 4xx or 5xx are handled by the URLSession.uploadTask?

How can I trigger the retrying on 5xx errors?

2

Answers


  1. Chosen as BEST ANSWER

    URLSession.uploadTask does not handle the http server side errors. It handles retrying and errors only for client side or network issues.

    The http status/error has to be retrieved from the task response casting it to an HTTPURLResponse.

    Directly from the uploadTask call (not supported by background URLSession):

    let task = uploadSession?.uploadTask(with: request, fromFile: fileURL, completionHandler: { data, response, error in
        if let error = error {
            print("Upload error:(error)")
            //Client side error
            return
        }
        
        guard let res = response as? HTTPURLResponse else {
            print("Upload completed with response:(response.description ?? "undefined")")
            //It should not happen at all
            return
        }
        
        if (200...299).contains(res.statusCode) {
            print("Upload completed successfully. Status code:(res.statusCode)")
        }
        else if (400...499).contains(res.statusCode) {
            print("Upload fatal issue. Status code:(res.statusCode)")
            //Fatal issue, do not retry the upload
        }
        else if (500...599).contains(res.statusCode) {
            print("Upload issue. Status code:(res.statusCode)")
            //Schedules a new uploading task for the file
        }
        else {
            print("Upload completed with status code:(res.statusCode)")
        }
    })
    

    or, if you are using a background URLSession, from the URLSessionTaskDelegate:

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        if let error = error {
            print("Upload error:(error)")
            //Client side error
            return
        }
    
        guard let res = task.response as? HTTPURLResponse else {
            print("Upload completed with response:(task.response?.description ?? "undefined")")
            //It should not happen at all
            return
        }
    
        if (200...299).contains(res.statusCode) {
            print("Upload completed successfully. Status code:(res.statusCode)")
        }
        else if (400...499).contains(res.statusCode) {
            print("Upload fatal issue. Status code:(res.statusCode)")
            //Fatal issue, do not retry the upload
        }
        else if (500...599).contains(res.statusCode) {
            print("Upload issue. Status code:(res.statusCode)")
            //Schedules a new uploading task for the file
        }
        else {
            print("Upload completed with status code:(res.statusCode)")
        }
    }
    

  2. Create the upload task like this:

    let task = uploadSession?.uploadTask(with: request, fromFile: fileURL, completionHandler: { data, response, error in
            if let error = error {
                print("Upload error: (error.localizedDescription)")
            } else {
                if let response = response as? HTTPURLResponse {
                    print("Response status code: (response.statusCode)")
                }
            }
        })
    
        task?.resume()
    

    you can handle errors and responsecode in the callback ☝️, alternatively
    you can look at URLSessionTaskDelegate and and URLSessionDataDelegate for a fine-grained control over the upload task.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search