iOS:didCompleteWithError、didReceive 响应未由 URLSession.uploadTask 触发

Posted

技术标签:

【中文标题】iOS:didCompleteWithError、didReceive 响应未由 URLSession.uploadTask 触发【英文标题】:iOS: didCompleteWithError, didReceive Response not triggered with URLSession.uploadTask 【发布时间】:2018-12-10 16:51:30 【问题描述】:

我想添加一个进度条来准确了解我的视频的上传百分比,但无法调用 didCompleteWithError、didReceive 响应、didSendBodyData bytesSent: Int64、totalBytesSent: Int64、totalB 等...

我很好地添加了委托,但无法发现问题。

@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

在另一个班级:

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)"
        
    

提前致谢

【问题讨论】:

在您的应用程序中,指向self 的委托指针是否设置为nil 不相关但不要在 Swift 中使用 NSMutable.. 类。使用var request = URLRequest() 并将body 创建为var body = Data() 并附加body += Data("--\(boundary)\r\n".utf8)。这个特殊的 Data 初始化器总是返回一个非可选的。 @Aaron Self 的信息不为零 【参考方案1】:

从你的类中移除 open 参数: https://***.com/a/38950955

简而言之:(来自其他帖子)

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.

【讨论】:

哇,它起作用了,所有的委托函数都被触发了。很奇怪,我相信open就是open的意思……

以上是关于iOS:didCompleteWithError、didReceive 响应未由 URLSession.uploadTask 触发的主要内容,如果未能解决你的问题,请参考以下文章

NSURLSession GET 请求:DidCompleteWithError - 错误为空

NSURLSessionTaskDelegate 方法 URLSession:task:didCompleteWithError: 从不调用

com.apple.AuthenticationServices.Authorization错误代码1000

NSURLSessionDownloadTask 在后台自动恢复所有任务

com.apple.AuthenticationServices.Authorization 错误代码 1000

在 Swift 3 中使用 downloadTask 没有这样的文件或目录错误