【问题标题】:How to cancel Alamofire.upload如何取消 Alamofire.upload
【发布时间】:2023-03-09 23:06:01
【问题描述】:

我正在通过Alamofire.upload 在服务器上上传图像作为多部分数据。与Alamofire.request 不同,它不返回Request 对象,我通常用它来取消请求。

但是像上传这样的消费请求能够取消是很合理的。在 Alamofire 中有哪些选项?

【问题讨论】:

    标签: swift alamofire


    【解决方案1】:

    在我的例子中,我在我的 API 类中创建了“sessionManager”实例,并为 Alamofire 的会话管理器分配了配置。

        var sessionManager: SessionManager!
    
        // Setup request manager
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForResource = TimeInterval(15.0)
        configuration.timeoutIntervalForRequest = TimeInterval(15.0)
        sessionManager = Alamofire.SessionManager(configuration: configuration)
    
    
        sessionManager.upload(multipartFormData: { multipartFormData in
    
            // AppendMultipart parts
            multipartFormData.append(metadataBodyPart, withName: PartName.Metadata, mimeType: MimeType.MultiPart)
            multipartFormData.append(imageDataBodyPart, withName: PartName.Photo, mimeType: MimeType.ImageJPG)
    
        } // ... rest of the code
    

    然后我可以创建一个方法来取消任何当前的请求类型。请注意,此处“(_,uploadTasks,_)”您还可以拥有“dataTasks”和“downloadTasks”,如果您愿意,也可以取消“(dataTasks,uploadTasks,downloadTasks)”

    func cancelUploadRequest() {
        sessionManager.session.getTasksWithCompletionHandler { (_, uploadTasks, _) in
            uploadTasks.forEach { $0.cancel() }
        }
    }
    

    你也可以这样:

    func cancel(request: CancelRequestType) {
        sessionManager.session.getTasksWithCompletionHandler { (dataTasks, uploadTasks, downloadTasks) in
            switch request {
                case .DataTask:
                    dataTasks.forEach { $0.cancel() }
                    print("- - - Data task was canceled!")
                case .UploadTask:
                    uploadTasks.forEach { $0.cancel() }
                    print("- - - Upload task was canceled!")
                case .DownloadTask:
                    downloadTasks.forEach { $0.cancel() }
                    print("- - - Download task was canceled!")
                case .ZeroTask:
                    print("- - - Zero tasks was found!")
            }
        }
    }
    

    其中“CancelRequestType”是枚举。所以你可以调用API.cancel(request: .UploadTask)之类的方法

    enum CancelRequestType: String {
        case DownloadTask = "DownloadTask"
        case DataTask = "DataTask"
        case UploadTask = "UploadTask"
        case ZeroTask = "Zero"
    }
    

    【讨论】:

      【解决方案2】:

      可以准备一个闭包,并将请求从“encodingCompletion”中转移出来

      class NetworkManager {
          private var closure: ((Request)->())?
      
          func startUpload() {
              Alamofire.upload(
                  .POST,
                  "https://httpbin.org/post",
                  multipartFormData: { multipartFormData in
                      multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
                      multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
                  },
                  encodingCompletion: { encodingResult in
                      switch encodingResult {
                      case .Success(let upload, _, _):
                          self.closure?(upload)
      
                          upload.responseJSON { response in
                              debugPrint(response)
                              uploadRequest = nil
                          }
                      case .Failure(let encodingError):
                          print(encodingError)
                      }
                  }
              )
          }
      }
      

      【讨论】:

        【解决方案3】:

        使用 Alamofire README 中的 Uploading MultiPartFormData 示例:

        Alamofire.upload(
            .POST,
            "https://httpbin.org/post",
            multipartFormData: { multipartFormData in
                multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
                multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
            },
            encodingCompletion: { encodingResult in
                switch encodingResult {
                case .Success(let upload, _, _):
                    upload.responseJSON { response in
                        debugPrint(response)
                    }
                case .Failure(let encodingError):
                    print(encodingError)
                }
            }
        )
        

        在这里,upload.responseJSON 返回一个Request,它应该允许您将其分配给某事以便稍后取消。例如:

        let request = upload.responseJSON {  ...
        
        ...
        
        request.cancel()
        

        【讨论】:

        • 如何在上传中添加参数(Swift 3)?
        • 我的应用总是在 request.cancel() 上崩溃,你是怎么成功的?
        【解决方案4】:

        恐怕你不能,根据 Alamofire 源代码,upload 函数在所有支持 MultipartFormData 的重载 except 中返回 Request 类型 见以下代码:

        // MARK: MultipartFormData
        
        /**
        Creates an upload request using the shared manager instance for the specified method and URL string.
        
        - parameter method:                  The HTTP method.
        - parameter URLString:               The URL string.
        - parameter headers: The HTTP headers. `nil` by default.
        - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
        - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. `MultipartFormDataEncodingMemoryThreshold` 
                                        by default.
        - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
        */
        public func upload(
          method: Method,
          URLString: URLStringConvertible,
          headers: [String: String]? = nil,
          multipartFormData: MultipartFormData -> Void,
          encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
          encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
        {
           return Manager.sharedInstance.upload(
              method,
              URLString,
              headers: headers,
              multipartFormData: multipartFormData,
              encodingMemoryThreshold: encodingMemoryThreshold,
              encodingCompletion: encodingCompletion
           )
        }
        
        /**
        Creates an upload request using the shared manager instance for the specified method and URL string.
        
        - parameter URLRequest:              The URL request.
        - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
        - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. `MultipartFormDataEncodingMemoryThreshold`
                                        by default.
        - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
        */
        public func upload(
          URLRequest: URLRequestConvertible,
          multipartFormData: MultipartFormData -> Void,
          encodingMemoryThreshold: UInt64 =    Manager.MultipartFormDataEncodingMemoryThreshold,
          encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
        {
           return Manager.sharedInstance.upload(
              URLRequest,
              multipartFormData: multipartFormData,
              encodingMemoryThreshold: encodingMemoryThreshold,
              encodingCompletion: encodingCompletion
           )
        }
        

        建议您在编写客户端代码时使用multipart/form-data,当您的表单包含任何<input type="file"> 元素时。

        因此,如果您只想将图像上传到服务器,您可以使用另一个 upload 函数重载,该函数返回一个 Request 对象,您可以像 Alamofire 文档中建议的那样取消它:

        let fileURL = NSBundle.mainBundle().URLForResource("Default", withExtension: "png")
        ler request =Alamofire.upload(.POST, "https://httpbin.org/post", file: fileURL)
        // request.cancel()
        

        希望对你有所帮助。

        【讨论】:

        • 这里有2个问题: 1.上传总是挂在2.03M,然后请求超时; 2. 无法获取服务器响应数据;
        猜你喜欢
        • 2019-07-21
        • 2017-01-29
        • 2019-06-11
        • 1970-01-01
        • 2018-11-27
        • 2019-03-30
        • 1970-01-01
        • 1970-01-01
        • 2017-09-02
        相关资源
        最近更新 更多