Upload Photo / File with JSON and custom headers via Swift 3 and Alamofire 4 | iOS | Swift
Asked Answered
H

3

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?

Hypertension answered 12/8, 2017 at 14:8 Comment(9)
are you getting any error on this snippet ?Sumatra
YES, i am getting HTTP CODE 400 with Message - Bad Request.Hypertension
can I have request URL? so I can try and check it in better waySumatra
Sorry! For security purpose i am not allowed to share the request URL.Hypertension
I guess this answer cis related to your issue. #41876419Golfer
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"Faitour
have you tried with URLSession?Photosynthesis
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]Whiffet
Did you add token_type before token in authorization header's value?Rondo
W
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
            }
        })
    }
Wildfire answered 11/9, 2017 at 8:46 Comment(0)
C
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.

Catamenia answered 8/9, 2017 at 5:1 Comment(0)
C
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)
}
Callable answered 8/9, 2017 at 12:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.