如何在 Alamofire 中上传文件并在参数中传递数据 - swift 5

Posted

技术标签:

【中文标题】如何在 Alamofire 中上传文件并在参数中传递数据 - swift 5【英文标题】:how to upload file and pass data in parameter in Alamofire - swift 5 【发布时间】:2020-01-27 00:38:16 【问题描述】:

我需要解决这个问题 我想上传一张图片到服务器,参数里面有数据

这是邮递员的要求

这是我的解决方案::

func createPhoto(name : String , email : String,gender:String,region:String,bod:String,activity_name:String,organisation_name:String,photo: UIImage, completion: @escaping (_ error: Error?, _ success: Bool)->Void) 

    var Token : String?
    var  tasksMO = [NSManagedObject]()
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "ConfirmActivationEntity")
    do 
        let results = try pe.context.fetch(request)
        tasksMO = results as! [NSManagedObject]
        for taskmo in tasksMO 
            Token = (taskmo.value(forKey: "access_token")  as! String )
        
        print("assbil")
     catch 
        print("fild")
    
    print(" Token :\(Token!)")

    let headers : HTTPHeaders = ["Authorization":"Bearer \(Token!)","X-HTTP-Method-Override":"PUT","Accept-Language" : Locale.current.languageCode ?? "ar", "Content-Type" : "application/x-www-form-urlencoded","Accept" : "application/json"]


    let parameters : Parameters = ["name" : name,"region":region,"activity_id":ActivityCode!,"organization_id":OrganizationCode!,"gender":gender,"job_id":JobCode!,"interest_id":IntrestedCode!,"organisation_name":organisation_name,"activity_name":activity_name,"bod":bod,"city":region,"email":email,"profile_pic":photo]

    guard let url = URL(string: "\(UrlApi.url)\(UrlApi.crateUser)") else  return 


    Alamofire.upload(multipartFormData:  (form: MultipartFormData) in

        for (key, value) in parameters 
            form.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
        

        //                if let data = imagedata
        //                    multipartFormData.append(data, withName: "imagename", fileName: "imagename.jpg", mimeType: "image/jpeg")
        //                

        if let data = photo.jpegData(compressionQuality: 0.5) 
            form.append(data, withName: "profile_pic", fileName: "photo.png", mimeType: "image/png")
        

    , usingThreshold: SessionManager.multipartFormDataEncodingMemoryThreshold, to: url,method: .post, headers: headers)  (result: SessionManager.MultipartFormDataEncodingResult) in

        switch result 
        case .failure(let error):
            print(error)
            completion(error, false)

        case .success(request: let upload, streamingFromDisk: _, streamFileURL: _):

            upload.uploadProgress(closure:  (progress: Progress) in
                print(progress)
            )
                .responseJSON(completionHandler:  (response: DataResponse<Any>) in

                    switch response.result
                    
                    case .failure(let error):
                        print(error)
                        completion(error, false)

                    case .success(let value):
                        let json = JSON(value)
                        print(json)

                        if let status = json["status"].toInt, status == 1 
                            // success
                            print("Upload Succeed")
                            completion(nil, true)
                         else 
                            print("Upload Failed")
                            completion(nil, false)
                        
                    

                )
        

    



而这个响应来自服务端:

responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo=NSDebugDescription=Invalid value around character 0.))

我在 ios 13、swift 5 和 Xcode 11 中使用 Alamofire pod 和 SwiftyJson pod

请帮帮我:)

【问题讨论】:

我认为您需要从“参数”字典中删除照片。您已经单独处理了照片。 @iyas-seyam 请检查我的答案,让我看看它是否有效。 【参考方案1】:

您应该在MultipartFormData 中传递图像数据,而不是与parameter 字典中的其他参数一起传递。

只需像下面这样更改您的代码并检查它是否正常工作。

//Remove profile pic param from parameters.
let parameters : Parameters = ["name" : name,"region":region,"activity_id":ActivityCode!,"organization_id":OrganizationCode!,"gender":gender,"job_id":JobCode!,"interest_id":IntrestedCode!,"organisation_name":organisation_name,"activity_name":activity_name,"bod":bod,"city":region,"email":email]

guard let url = URL(string: "\(UrlApi.url)\(UrlApi.crateUser)") else  return 

Alamofire.upload(multipartFormData:  (form: MultipartFormData) in

          for (key, value) in parameters 
               form.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
          

          if let data = photo.jpegData(compressionQuality: 0.5) 
               form.append(data, withName: "profile_pic", fileName: "photo.png", mimeType: "image/png")
          
 

【讨论】:

不幸的是它对我不起作用,我向它添加了更多代码,它也不起作用【参考方案2】:

不要在参数字典中包含图像。或者在添加到 MultipartFormData 时跳过它,如下所示

Alamofire.upload(multipartFormData:  form in
    for (key, value) in parameters 
        if !(value is UIImage), let data = "\(value)".data(using: .utf8) 
            form.append(data, withName: key as String)
        
    
    if let data = photo.jpegData(compressionQuality: 0.5) 
        form.append(data, withName: "profile_pic", fileName: "photo.png", mimeType: "image/png")
    

【讨论】:

以上是关于如何在 Alamofire 中上传文件并在参数中传递数据 - swift 5的主要内容,如果未能解决你的问题,请参考以下文章

Swift 4:如何使用 Alamofire 在参数中发布文件?

Alamofire 上传带有进度的大文件并在应用重启时显示进度

如何使用 Alamofire.upload 函数上传带有一些参数的图片或 wav 文件

如何在 Swift 中使用 Alamofire 上传带有 JSON 参数的图像?

为啥我不能将文件附加为 Alamofire 中的参数值之一?

如何在 Swift 4 中使用 Alamofire 上传具有其他参数的多个图像