8

I need to call the Multipart request with Image file and JSON.

I have tried this, but still getting the error.

 // define parameters
  let parameters = [
    "hometown": "yalikavak",
    "living": "istanbul"
  ]

Alamofire.upload(multipartFormData: { multipartFormData in
    if let imageData = UIImageJPEGRepresentation(image, 1) {
      multipartFormData.append(imageData, withName: "file", fileName: "file.png", mimeType: "image/png")
    }

    for (key, value) in parameters {
      multipartFormData.append((value?.data(using: .utf8))!, withName: key)
    }}, to: "upload_url", method: .post, headers: ["Authorization": "auth_token"],
        encodingCompletion: { encodingResult in
          switch encodingResult {
          case .success(let upload, _, _):
            upload.response { [weak self] response in
              guard let strongSelf = self else {
                return
              }
              debugPrint(response)
            }
          case .failure(let encodingError):
            print("error:\(encodingError)")
          }
  })
}

How to send the JSON?

James Z
  • 12,209
  • 10
  • 24
  • 44
Shoeb Siddique
  • 2,805
  • 1
  • 22
  • 42
  • are you getting any error on this snippet ? – Maulik Pandya Aug 12 '17 at 16:43
  • YES, i am getting HTTP CODE 400 with Message - Bad Request. – Shoeb Siddique Aug 14 '17 at 05:30
  • can I have request URL? so I can try and check it in better way – Maulik Pandya Aug 14 '17 at 08:40
  • Sorry! For security purpose i am not allowed to share the request URL. – Shoeb Siddique Aug 16 '17 at 05:52
  • 1
    I guess this answer cis related to your issue. https://stackoverflow.com/questions/41875919/serializationfailure-error-while-posting-data-with-alamofire – RviOS Aug 16 '17 at 05:53
  • Try encoding your image with `UIImagePNGRepresentation(image)` as you are setting the mimeType to `"image/png"` or try setting the mimeType to `"image/jpeg"` with fileName `"file.jpg"` – Micah Wilson Sep 06 '17 at 20:39
  • have you tried with URLSession? – Yuyutsu Sep 08 '17 at 05:21
  • try sending params this way, all other part of your code remain same: let yourParams = [ "hometown": "yalikavak", "living": "istanbul" ] let jsonParams = try! JSONSerialization.data(withJSONObject: yourParams) let jsonParamsString = String(data: jsonParams, encoding: String.Encoding.utf8) print(jsonParamsString ?? "") //Make single server param name for all dictionary items let paramsToSend = ["paramNameFromServer":jsonParamsString] – Aadil Ali Sep 08 '17 at 06:13
  • Did you add `token_type` before `token` in authorization header's value? – Max Potapov Sep 11 '17 at 12:37

3 Answers3

4

Try This Code for Multiple upload Images in Single Request, This code is already working.

     // For Pass Valid Parameters & number of Images in Array in Image Upload Function
     var dicImgData : NSMutableDictionary? = NSMutableDictionary()

     if let img = UIImage(named: "Your Image") {
         if let data:Data = UIImagePNGRepresentation(img) {
             var imageData : NSData = data
             dicImgData! .setObject(imageData, forKey: "data" as NSCopying)
             dicImgData! .setObject("file", forKey: "name" as NSCopying)
             dicImgData! .setObject("file.png", forKey: "fileName" as NSCopying)
             dicImgData! .setObject("image/png", forKey: "type" as NSCopying)

             let dicParameter = [
                 "hometown": "yalikavak",
                 "living": "istanbul"
             ]

             self.uploadImage(url: "Your URL", Parameter: dicParameter, Images: [dicImgData])
         }
    }

Upload Function

    func uploadImage (url: String, Parameter param : NSDictionary, Images arrImage: NSArray) -> Void
    {
        var requestURL : String! = url
        let headers = [
            "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
            "Accept": "application/json",
            ]

        print("---------------------")
        print("Request URL :- \(requestURL)")
        print("---------------------")

        Alamofire.upload(multipartFormData: { (data) in

            for (key, value) in param {
                data.append((value as! String).data(using: .utf8)!, withName: key as! String)
            }

            for imageInfo in arrImage
            {
                var dicInfo : NSDictionary! = imageInfo as! NSDictionary
                data.append(dicInfo["data"] as! Data, withName: dicInfo["name"] as! String, fileName: dicInfo["fileName"] as! String, mimeType: dicInfo["type"] as! String)
                dicInfo = nil
            }

        }, to: requestURL, method: .post , headers:nil, encodingCompletion: { (encodeResult) in
            switch encodeResult {
            case .success(let upload, _, _):

                upload.responseJSON(completionHandler: { (response) in

                    switch response.result
                    {
                    case .success(let responseJSON):
                        guard let dicResponse = responseJSON as? NSDictionary else{
                            return
                        }

                        print("Response : \((dicResponse))")

                    case .failure(let error):

                        print(error)

                        break
                    }
                })
            case .failure(let error):
                print(error)
                break
            }
        })
    }
Virajkumar Patel
  • 1,533
  • 12
  • 19
2

From data you have given, I comes to an conclusion as given below.

The status code 400 means json you're passing to the api was not following the api documentation. For example if they expect a key "name" and you're not given such a key at all.

Other possible reasons for this error.

Seems like you haven't mentioned any of content types

Add these line of code to assure that the response and your request are in proper formats

Alamofire.request(.GET, "your url", parameters: ["foo": "bar"])
         .validate(statusCode: 200..<300)
         .validate(contentType: ["application/json"])
         .response { (_, _, _, error) in
                  println(error)
         }

The Accept header tells the server what your client wants in the response. The Content-Type header tells the server what the client sends in the request.

If you can give more information we can help further.

Saranjith
  • 11,242
  • 5
  • 69
  • 122
1

Here I made my custom webservice, You can use it. This webservice is for upload dictionary with image and video or both or without it.

import Foundation
import Alamofire
class WebServiceHandler: AnyObject {

    func uploadWithAlamofire(Parameters params : [NSObject : AnyObject]?,ImageParameters imgparams :  [NSObject : AnyObject]?,VideoParameters vidoparam :  [NSObject : AnyObject]?,Action action : NSString, success: @escaping (AnyObject) -> Void, failure: @escaping (AnyObject) -> Void)
    {
        var base_url = "http://benzatineinfotech.com/webservice/finder/index.php/Web_api/"
        base_url.append(action as String)

        Alamofire.upload(multipartFormData: { multipartFormData in
            if imgparams != nil{
                for (key, value) in imgparams! {
                    if let imageData = UIImageJPEGRepresentation(value as! UIImage, 1) {
                        multipartFormData.append(imageData, withName: key as! String, fileName: "\(NSDate().timeIntervalSince1970 * 1000)).jpg", mimeType: "image/jpg")
                    }
                }
            }
            if vidoparam != nil{
                for (key, value) in vidoparam! {
                    multipartFormData.append(value as! URL , withName: key as! String, fileName: "\(NSDate().timeIntervalSince1970 * 1000).mp4", mimeType: "application/octet-stream")
                }
            }
            if params != nil
            {
                for (key, value) in params! {
                    multipartFormData.append((value as! String).data(using: .utf8)!, withName: key as! String)
                }

            } }, to: base_url, method: .post, headers: nil,
                 encodingCompletion: { encodingResult in
                    switch encodingResult {
                    case .success(let upload, _, _):
                        upload.uploadProgress { progress in
                            print(progress.fractionCompleted)
                        }
                        upload.response { [weak self] response in
                            guard self != nil else {
                                return
                            }
                            let responseString = String(data: response.data!, encoding: String.Encoding.utf8)
                            return success(responseString as AnyObject)

                        }
                    case .failure(let encodingError):
                        print("error:\(encodingError)")
                        return failure(encodingError as AnyObject)
                    }
        })
    }
    func convertToDictionary(text: String) -> [String: Any]? {
        if let data = text.data(using: .utf8) {
            do {
                return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            } catch {
                print(error.localizedDescription)
            }
        }
        return nil
    }
}

Usage:

self.webservice.uploadWithAlamofire(Parameters: dict_params as [NSObject : AnyObject], ImageParameters: imgparam as [NSObject : AnyObject], VideoParameters:  videoparam as [NSObject : AnyObject], Action: "write_message", success: { (success) in
        print(success)
}) { (error) in
        print(error)
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Jitendra Modi
  • 2,344
  • 12
  • 34