使用 alamofire 的多部分/表单数据

Posted

技术标签:

【中文标题】使用 alamofire 的多部分/表单数据【英文标题】:multipart/form-data using alamofire 【发布时间】:2017-08-15 01:18:21 【问题描述】:

我正在进行 .post API 调用,我需要使用 multipart/form-data。我知道如何使用 JSON 进行调用,但我不熟悉 multipart/form-data。使用 JSON,这是一个超级简单的调用。只需创建一个类型参数:

var parameters:Parameters = [:]
parameters["username"] = emailTextField.text!
parameters["password"] = passwordTextField.text!

Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON  (response) in
    //Code here 

我们将如何使用表单数据来编写它。最简单的方法是什么?我不需要上传任何文件或任何东西。我所要做的就是用上述极其简单的项目进行调用。使用表单数据执行此操作的最简洁方法是什么。我确信这是一个非常基本的问题,我四处寻找有关堆栈溢出的帮助,但我只看到这被用于更高级的文件调用。我只是想知道如何以最简单的方式做到这一点,作为 JSON 调用的替代品。

【问题讨论】:

见github.com/Alamofire/Alamofire#uploading-multipart-form-data 如果我们使用该方法,我们如何放入标题? 【参考方案1】:

文档中的示例:

Alamofire.upload(
    multipartFormData:  multipartFormData in
        multipartFormData.append(unicornImageURL, withName: "unicorn")
        multipartFormData.append(rainbowImageURL, withName: "rainbow")
    ,
    to: "https://httpbin.org/post",
    encodingCompletion:  encodingResult in
        switch encodingResult 
        case .success(let upload, _, _):
            upload.responseJSON  response in
                debugPrint(response)
            
        case .failure(let encodingError):
            print(encodingError)
        
    
)

方法的完整描述(如果需要设置headers.Source):

/// Encodes `multipartFormData` using `encodingMemoryThreshold` with the default `SessionManager` and calls
/// `encodingCompletion` with new `UploadRequest` using the `url`, `method` and `headers`.
///
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
/// used for larger payloads such as video content.
///
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
/// technique was used.
///
/// - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
///                                      `multipartFormDataEncodingMemoryThreshold` by default.
/// - parameter url:                     The URL.
/// - parameter method:                  The HTTP method. `.post` by default.
/// - parameter headers:                 The HTTP headers. `nil` by default.
/// - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
public func upload(
    multipartFormData: @escaping (MultipartFormData) -> Void,
    usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
    to url: URLConvertible,
    method: HTTPMethod = .post,
    headers: HTTPHeaders? = nil,
    encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?)

【讨论】:

【参考方案2】:

在 swift 4 和 Alamofire 4.7 中

多部分/表单数据请求

 let email = emailTextField.text!
 let password  = passwordTextField.text!
Alamofire.upload(
            multipartFormData:  multipartFormData in
                multipartFormData.append((email.data(using: String.Encoding.utf8, allowLossyConversion: false))!, withName: "email")
                multipartFormData.append((password.data(using: String.Encoding.utf8, allowLossyConversion: false))!, withName: "password")
 ,
            to: url,
            encodingCompletion:  encodingResult in
                switch encodingResult 
                case .success(let upload, _, _):
                    upload.responseData  response in
                   debugPrint(response)
                    
                case .failure(let encodingError):
                    print(encodingError)

                
        
        )

【讨论】:

【参考方案3】:
//MARK: Uploading Multiple Images/File with Parameters
static func uploadMultipleImageWithParamters(aryImage:NSArray,webserviceName:String,postDataDict: String?, completion:@escaping (_ IsSuccess:Bool,_ Response:Any,_ CheckInternet:String) -> Void)


    if isInternetAvailable() == false
    
        let Alert = Customalert()
        Alert.msg(message: msgInternet)
        completion(false,"",objNoInternet)
        return
    
    let parameters = self.convertToDictionary(text: postDataDict!)
    if parameters == nil

        let Alert = Customalert()
        Alert.msg(message: "Please Check you Json")
        completion(false,"","")
        return
    
    Alamofire.upload(
        multipartFormData:  multipartFormData in

            for i in 0..<aryImage.count
            
                let imageData = UIImagePNGRepresentation(aryImage.object(at: i) as! UIImage)
                multipartFormData.append(imageData!, withName: "Photo\(i)", fileName: "\(Date().timeIntervalSince1970).jpeg", mimeType: "image/jpeg")
            

            for (key, value) in parameters! 

                if value is String
                
                     multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
                
                else if value is NSDictionary
                
                    let dataExample: Data = NSKeyedArchiver.archivedData(withRootObject: value as! NSDictionary)
                    multipartFormData.append(dataExample, withName: key)

                else if value is NSArray
                
                    let objData = NSKeyedArchiver.archivedData(withRootObject: value as! NSArray)
                    multipartFormData.append(objData, withName: key)
                
            
    ,
        to: baseURL + "\(webserviceName)",
        encodingCompletion:  encodingResult in

            switch encodingResult 
            case .success(let upload, _, _):
                upload.responseString  response in
                    debugPrint(response)
                    print(response)
                    completion(true,response.value!,"")
                    
                    .uploadProgress  progress in // main queue by default
                        print("Upload Progress: \(progress.fractionCompleted)")
                
                return
            case .failure(let encodingError):

                debugPrint(encodingError)
            
    )

【讨论】:

以上是关于使用 alamofire 的多部分/表单数据的主要内容,如果未能解决你的问题,请参考以下文章

具有特定 JSON 要求的多部分表单数据 POST

如何处理Alamofire中的多部分/相关数据?

使用 Alamofire 的多部分 POST

带有 JSON 参数的多部分数据 Alamofire

在应用程序被杀死后在应用程序启动时恢复未完成的多部分/表单数据上传任务

Alamofire - 多部分表单数据键:值