1

I'm using Alamofire to upload image on server, this method working fine and I have already used in many projects.

I have used following code to upload image on my server using multiform data.

Alamofire.upload( multipartFormData: { multipartFormData in

    for (key, value) in parameters {
        if let data = (value as! String).data(using: .utf8) {
            multipartFormData.append(data, withName: key)
        }
    }

    let imageData = image?.pngData()

    multipartFormData.append(imageData!, withName: "profile_image", fileName: "profileImage", mimeType: "")

}, to: getURL(.addProfile), headers: getHeaders(), encodingCompletion: { encodingResult in

    switch encodingResult {

    case .success(let upload, _, _):

        upload.response(completionHandler: { (defaultDataResponse) in

            guard let httpResponse = defaultDataResponse.response else {
                completion(nil, defaultDataResponse.error)
                return
            }

            if httpResponse.statusCode == 200 {

                do {

                    let genericModel = try JSONDecoder().decode(ProfileImageModel.self, from: defaultDataResponse.data!)
                    completion(genericModel, nil)

                } catch {

                    completion(nil, error)
                }

            } else {
                completion(nil, defaultDataResponse.error)
            }
        })

    case .failure(let encodingError):
        completion(nil, encodingError)
    }
})

This works fine.

My issue is here, where extra parameter passing in api.

for (key, value) in parameters {
    if let data = (value as! String).data(using: .utf8) {
        multipartFormData.append(data, withName: key)
    }
}

Above code will convert string value to data and append to multipartFormData. And it's works for following type of request structure.

{
    "first_name": "ABC",
    "last_name": "XYZ",
    "bio": "iOS Developer"
}

What to do when I have following type of request structure?

{
    "first_name": "ABC",
    "last_name": "XYZ",
    "bio": "iOS Developer"
    "location": {
        "full_address": "My Location",
        "latitude": "23.0000",
        "longitude": "76.0000"
    }
}

Please help to achieve this.

piet.t
  • 11,718
  • 21
  • 43
  • 52
Mayur Karmur
  • 2,119
  • 14
  • 35

1 Answers1

2

Use this function

 func requestUploadImage(_ strURL : String, imageData : Data? ,params : [String : AnyObject]?, headers : [String : String]?, success:@escaping (NSDictionary) -> Void, failure:@escaping (Error) -> Void){
//        let  params = ["id": "101", "name": "Navin", "timezone": "2018-07-26  03:17:06" , "image": imageData] as [String : AnyObject]
  //
        //  CommonMethodsModel.showProgrssHUD()
    let url = URL(string: baseURL + strURL)!
    let parameters = params //Optional for extra parameter

        Alamofire.upload(multipartFormData: { multipartFormData in
            multipartFormData.append(imageData!, withName: "image",fileName: "file.jpeg", mimeType: "image/jpeg")
            print(imageData , params)
            for (key, value) in parameters! {
                multipartFormData.append(value.data(using: String.Encoding.utf8.rawValue)!, withName: key)
            } //Optional for extra parameters
        },
                 usingThreshold: UInt64.init(),         to:url, method: .post)
        { (result) in
//             CommonMethodsModel.HidePrgressHUD()
            switch result {
            case .success(let upload, _, _):

                upload.uploadProgress(closure: { (progress) in
                    print("Upload Progress: \(progress.fractionCompleted)")
                })

                upload.responseJSON { response in
                    print(response.result.value)

                    success(response.result.value as! NSDictionary )
                }

            case .failure(let encodingError):
                print(encodingError)
            }
        }

    }
NavinBagul
  • 741
  • 7
  • 24
  • I'm using same method, just check my structure of parameters. This will not works when there are location object, application will crash. – Mayur Karmur Mar 28 '19 at 09:12
  • 1
    @MayurKarmur Instead of using location object, why dont you create dict of location and use it. Have you tried this? – dahiya_boy Mar 28 '19 at 09:16
  • I am using this code and it works absolutely fine in my projects for complex array dictionary combination, check *params* in my method. – NavinBagul Mar 28 '19 at 09:17
  • @NavinBagul Just wanted to know, what is `withName` and `fileName` in multipart. I never able figure out the difference. P.s. try to use `[String : Any]` and avoid `AnyObject`. – dahiya_boy Mar 28 '19 at 09:52
  • 1
    @dahiya_boy i think withName and fileName are just string which you can pass whatever you want. – Zღk Mar 28 '19 at 10:05
  • 1
    @dahiya_boy 1) name : The name to associate with the data in the `Content-Disposition` HTTP header. 2)fileName: The filename to associate with the data in the `Content-Disposition` HTTP header.3)mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header. https://github.com/Alamofire/Alamofire/blob/0351aebc5fe0f3a04f7a0e666c7faf95fbdd2826/Source/MultipartFormData.swift – NavinBagul Mar 28 '19 at 10:26
  • @dahiya_boy name : your api key like "loginName" : Dahiya ,,, fileName :- whichname you want to save file in DB , like name.jpg , mimeType : type of file – NavinBagul Apr 10 '19 at 06:49