iosswifturlsessionnsurlsessionuploadtask

iOS: didCompleteWithError, didReceive Response not triggered with URLSession.uploadTask


I would like to add a progress bar for knowing exactly the percent of upload of my video, but impossible to call the didCompleteWithError, didReceive response, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalB etc...

I added well the delegate, but impossible to catch the problem.

@objcMembers open class DAL : NSObject
{
    var response: URLResponse?
    var session: URLSession?
    var uploadTask: URLSessionUploadTask?
    let opQueue = OperationQueue()

    static let sharedInstance = DAL()
    fileprivate let showLogs = true

    var WSURL:String =  SERVER_PROTOCOL + DOMAIN_NAME_ADDRESS //"http://localhost:3000"
    var eventKey:String = EVENT_TO_USE
}

In another class:

extension DAL: URLSessionDelegate,URLSessionDataDelegate, URLSessionTaskDelegate
{

        func uploadVideo(_ videoPath: String, fileName: String, eventId: Int, contactId: Int, type: Int, callback: @escaping (_ data:Data?, _ resp:HTTPURLResponse?, _ error:NSError?) -> Void)
            {
                // let filePath = video

                // let videoFileURL = NSURL(fileURLWithPath: videoPath)
                var video_data: NSData?
                do {
                    video_data = try NSData(contentsOfFile: (videoPath), options: NSData.ReadingOptions.alwaysMapped)
                } catch _ {
                    video_data = nil
                    return
                }

                let WSURL:String =  "https://" + "ren.newp.fr/node"



            let requestURLString = "\(WSURL)/regtions/lead/photo//"
            let url = URL(string: requestURLString)
            #if DEBUG
            print(requestURLString)
            #endif
            let request = NSMutableURLRequest(url: url!)
            request.httpMethod = "POST"

            let boundary = generateBoundaryString()

            //define the multipart request type
            request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

            let body = NSMutableData()
            let mimetype = "video/mp4"

            //define the data post parameter

            body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
            body.append("Content-Disposition:form-data; name=\"eventId\"\r\n\r\n".data(using: String.Encoding.utf8)!)
            body.append("\(eventId)\r\n".data(using: String.Encoding.utf8)!)

            body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
            body.append("Content-Disposition:form-data; name=\"contactId\"\r\n\r\n".data(using: String.Encoding.utf8)!)
            body.append("\(contactId)\r\n".data(using: String.Encoding.utf8)!)

            body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
            body.append("Content-Disposition:form-data; name=\"type\"\r\n\r\n".data(using: String.Encoding.utf8)!)
            body.append("\(type)\r\n".data(using: String.Encoding.utf8)!)

            body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
            body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fileName)\"\r\n".data(using: String.Encoding.utf8)!)
            body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
            body.append(video_data! as Data)
            body.append("\r\n".data(using: String.Encoding.utf8)!)

            body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)

            request.httpBody = body as Data
             request.setValue("Keep-Alive", forHTTPHeaderField: "Connection")

            let config = URLSessionConfiguration.default
            self.session = URLSession(configuration: config, delegate: self, delegateQueue: self.opQueue)
            let fileUrl = URL(string:"\(videoPath)/\(fileName)")

            if let task = session?.uploadTask(with: request as URLRequest, from: video_data! as Data){
                task.resume()}
        }

        private func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            // the task finished
            if let err = error {
                print("Error: \(err.localizedDescription)")
            } else {
                print("The upload was successful.")
                self.session?.finishTasksAndInvalidate()
            }  // end if
        }  // end func

        private func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
            print("did receive response")
            self.response = response
            print(self.response!)
            completionHandler(URLSession.ResponseDisposition.allow)
        }  // end func

        private func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
            let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
            print(progress)
        }  // end func


        public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
            completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
        }

        func generateBoundaryString() -> String
        {
            return "Boundary-\(UUID().uuidString)"
        }
    }
}

Thanks in advance


Solution

  • Remove the open parameter from your class: https://stackoverflow.com/a/38950955

    In short: (from the other post)

    An open class is accessible and subclassable outside of the defining module. An open class member is accessible and overridable outside of the defining module.
    A public class is accessible but not subclassable outside of the defining module. A public class member is accessible but not overridable outside of the defining module.