Alamofire multipartFormData using [String : Any] parameters - ios

Hello I am trying to post a parameter and/or image.
My parameter is a [String : Any] with string, date, int, values.
When I post only a parameter I use URLEncoding.default encoding. However when I need to post both parameter and image I use multipartFormData.
My code is below
if url == ""{
AF.upload(multipartFormData: { multipartFormData in
for (key,value) in parameters {
multipartFormData.append((value as! String).data(using: .utf8)!, withName: key)
}
let jpegData = art!.jpegData(compressionQuality: 1.0)
multipartFormData.append(Data((jpegData)!), withName: "photo")
}, to: "\(NetworkManager.rootURL)/api/add/")
.responseJSON { response in
debugPrint(response)
}
}else{
AF.request("\(NetworkManager.rootURL)/api/add/", method: .post, parameters: parameters, encoding: URLEncoding.default, headers: nil).response { (reponse) in
let status = reponse.response!.statusCode
if status == 200{
completion(200)
}else{
completion(401)
}
}
}
My problem is that because my parameter is a any with string date int values I get a
Could not cast value of type 'Swift.Int' (0x1c3f1f1e8) to 'Swift.String' (0x1c3f21390). Is there any workaround for this? or do I have to change everything to string...
Any help is appreciated

You need to path any value as a String for this to work as it's the only way to transfer it to Data , some others use
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}

I have maked block function for Upload image with parameter to Server Using Multipart
//Here strUrl = YOUR WEBSERVICE URL
//postParam = post Request parameter i.e.
//let postParam : [String : Any] = [first_name : "name"]
//imageArray = image upload array i.e.
//var imageArray : [[String:Data]] = [["image_name" : YOUR IMAGE DATA]]
func postImageRequestWithURL(withUrl strURL: String,withParam postParam: Dictionary<String, Any>,withImages imageArray:[[String:Data]], completion:#escaping (_ isSuccess: Bool, _ response:NSDictionary) -> Void)
{
let requetURL = strURL
Alamofire.upload(multipartFormData: { (MultipartFormData) in
for (imageDic) in imageArray
{
for (key,value) in imageDic
{
MultipartFormData.append(value, withName:key,fileName: "file.jpg", mimeType: "image/jpg")
}
}
for (key, value) in postParam
{
MultipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
// MultipartFormData.append(value, withName: key)
}
}, usingThreshold: UInt64.init(), to: requetURL, method: .post, headers: ["Accept": "application/json"]) { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
let desiredString = NSString(data: response.data!, encoding: String.Encoding.utf8.rawValue)
print("Response ====================")
print(desiredString!)
if let json = response.result.value as? NSDictionary
{
if response.response?.statusCode == 200
|| response.response?.statusCode == 201
|| response.response?.statusCode == 202
{
completion(true,json);
}
else
{
completion(false,json);
}
}
else
{
completion(false,[:]);
}
}
case .failure(let encodingError):
print(encodingError)
completion(false,[:]);
}
}
}
You can also upload multiple image using this
I Hope this will help...

Related

Upload files with parameters from multipartformdata using alamofire 5 in ios swift

I am trying upload files with parameters (multipartformdata) but i can't do it with new version Alamofire 5, if you have some experience with Alamofire 5 please share it with me.
func uploadPluckImage(imgData : Data, imageColumnName : String, url:String,httpmethod:HTTPMethod,completionHandler: #escaping (NSDictionary?, String?) -> ()){
let token = UserDefaults.standard.string(forKey: PrefKeys.loginToken) ?? ""
let authorization = ["Authorization" : "Bearer \(token)"]
let parameters: Parameters?
parameters = [
"garbageCollector": 0,
"stuff_uuid": "2b4b750a-f4a6-4d61-84ce-7c42b5c030ee",
"delete_file" : ""
]
let headers : HTTPHeader?
headers = ["Authorization" : "Bearer \(token)"]
let imageURl = "http://68.183.152.132/api/v1/stuff/uploader"
AF.upload(multipartFormData: { (multipart: MultipartFormData) in
let imageData = self.firstImage.image?.jpegData(compressionQuality: 0.7)
multipart.append(imageData, withName: "file", fileName: "file.png", mimeType: "image/png")
for (key, value) in parameters!{
multipart.append(value as! String).data(using: .utf8)!, withName: key)
}
},usingThreshold: UInt64.init(),
to: imageURl,
method: .post,
headers: headers,
encodingCompletion: { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Uploading")
})
break
case .failure(let encodingError):
print("err is \(encodingError)")
break
}
})
}
Upload method slightly changed in Alamofire 5
func upload(image: Data, to url: Alamofire.URLRequestConvertible, params: [String: Any]) {
AF.upload(multipartFormData: { multiPart in
for (key, value) in params {
if let temp = value as? String {
multiPart.append(temp.data(using: .utf8)!, withName: key)
}
if let temp = value as? Int {
multiPart.append("\(temp)".data(using: .utf8)!, withName: key)
}
if let temp = value as? NSArray {
temp.forEach({ element in
let keyObj = key + "[]"
if let string = element as? String {
multiPart.append(string.data(using: .utf8)!, withName: keyObj)
} else
if let num = element as? Int {
let value = "\(num)"
multiPart.append(value.data(using: .utf8)!, withName: keyObj)
}
})
}
}
multiPart.append(image, withName: "file", fileName: "file.png", mimeType: "image/png")
}, with: url)
.uploadProgress(queue: .main, closure: { progress in
//Current upload progress of file
print("Upload Progress: \(progress.fractionCompleted)")
})
.responseJSON(completionHandler: { data in
//Do what ever you want to do with response
})
}
Hope this will help you
EDIT: In case you don't quite get the above, here is an expansion:
let uploadRequest: UploadRequest = AF.upload(multipartFormData: multipartFormData, with: ...)
let completionHander: (AFDataResponse<Any>) -> Void) = { result in
//Do what ever you want to do with response, which is a DataResponse<Success, AFError>
}
// Adds that completion hander to the UploadRequest
uploadRequest.responseJSON(completionHandler: completionHander)
This how I upload images and videos from a swift 5 app with Alamofire 5.
Images
/**
Send Image to server
*/
func Post(imageOrVideo : UIImage?){
let headers: HTTPHeaders = [
/* "Authorization": "your_access_token", in case you need authorization header */
"Content-type": "multipart/form-data"
]
AF.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(imageOrVideo!.jpegData(compressionQuality: 0.5)!, withName: "upload_data" , fileName: "file.jpeg", mimeType: "image/jpeg")
},
to: "http://ip.here.--.--/new.php", method: .post , headers: headers)
.response { resp in
print(resp)
}
}
You can create a temporary resource and use the temporary url (good for videos):
/**
Send video to server
*/
func PostVideoUrl(url : URL){
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
AF.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(url, withName: "upload_data" , fileName: "movie.mp4", mimeType: "video/mp4")
},
to: "http://ip.here.--.--/newVideo.php", method: .post , headers: headers)
.response { resp in
print(resp)
}
}
This Is work for me Using Swift 4.2 Please try this
let url = "http://google.com" /* your API url */
let headers: HTTPHeaders = [
/* "Authorization": "your_access_token", in case you need authorization header */
"Content-type": "multipart/form-data"
]
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = imageData{
multipartFormData.append(data, withName: "image", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded")
if let err = response.error{
onError?(err)
return
}
onCompletion?(nil)
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
onError?(error)
}
}
func upload(image: Data, to url: URL, params: [String: Any]) {
let block = { (multipart: MultipartFormData) in
URLEncoding.default.queryParameters(params).forEach { (key, value) in
if let data = value.data(using: .utf8) {
multipart.append(data, withName: key)
}
}
multiPart.append(image, withName: "file", fileName: "file.png", mimeType: "image/png")
}
AF.upload(multipartFormData: block, to: url)
.uploadProgress(queue: .main, closure: { progress in
//Current upload progress of file
print("Upload Progress: \(progress.fractionCompleted)")
})
.responseJSON(completionHandler: { data in
//Do what ever you want to do with response
})
}
extension URLEncoding {
public func queryParameters(_ parameters: [String: Any]) -> [(String, String)] {
var components: [(String, String)] = []
for key in parameters.keys.sorted(by: <) {
let value = parameters[key]!
components += queryComponents(fromKey: key, value: value)
}
return components
}
}
Upload two images with parameters with Headers , Using Alamofire 5
i solve this issue try this code ..
//MARK: Upload Images with Params API's
func upload(icon: Data, image : Data, params: [String: Any]) {
let urlString = "Your URL String "
let headers: HTTPHeaders =
["Content-type": "multipart/form-data",
"Accept": "application/json"]
AF.upload(
multipartFormData: { multipartFormData in
for (key, value) in params {
if let temp = value as? String {
multipartFormData.append(temp.data(using: .utf8)!, withName: key)}
if let temp = value as? Int {
multipartFormData.append("(temp)".data(using: .utf8)!, withName: key)}
if let temp = value as? NSArray {
temp.forEach({ element in
let keyObj = key + "[]"
if let string = element as? String {
multipartFormData.append(string.data(using: .utf8)!, withName: keyObj)
} else
if let num = element as? Int {
let value = "(num)"
multipartFormData.append(value.data(using: .utf8)!, withName: keyObj)
}
})
}
}
multipartFormData.append(icon, withName: "icon", fileName: "icon.png", mimeType: "icon/png")
multipartFormData.append(image, withName: "registerImage", fileName: "registerImage.png", mimeType: "registerImage/png")
},
to: urlString, //URL Here
method: .post,
headers: headers)
.responseJSON { (resp) in
defer{SVProgressHUD.dismiss()}
print("resp is \(resp)")
}
}##
Heading
#
You can do that using Router URLRequestConvertible
static func performMultiPartFile<T:Decodable>(imageData: Data, route:APIRoute,decoder: JSONDecoder = JSONDecoder(), completion: #escaping (_ result: T?, _ error: String?) -> ()) {
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imageData, withName: "image", fileName: "iosImage.jpg", mimeType: "image/jpg")
}, with: route) { (encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.responseString { (response) in
if response.result.isSuccess {
if let JSON = response.result.value {
debugPrint("✅ Respons Object >>>> " + String(describing: JSON))
do {
let result = try JSONDecoder().decode(T.self, from: JSON.data(using: .utf8)!)
debugPrint("✍️ Result: " + String(describing: result))
completion(result, nil)
} catch let error { // mapping fail
debugPrint("❌ Error in Mapping" + String(describing: error))
completion(nil, String(describing: error))
}
}
} else {
debugPrint("❌ 😝 Response fail : \(response.result.description)")
completion(nil, (response.result.error?.localizedDescription)!)
}
}
case .failure(let encodingError):
completion(nil, String(describing: encodingError))
}
}
}
This is work with params.
func uploadImage(isUser:Bool, endUrl: String, imageData: Data?, parameters: [String : Any], onCompletion: ((_ isSuccess:Bool) -> Void)? = nil, onError: ((Error?) -> Void)? = nil){
headers = [
"Accept": "application/json",
"Content-type": "multipart/form-data"
]
AF.upload(multipartFormData: { multipartFormData in
for (key, value) in parameters {
if let temp = value as? String {
multipartFormData.append(temp.data(using: .utf8)!, withName: key)
}
if let temp = value as? Int {
multipartFormData.append("\(temp)".data(using: .utf8)!, withName: key)
}
if let temp = value as? NSArray {
temp.forEach({ element in
let keyObj = key + "[]"
if let string = element as? String {
multipartFormData.append(string.data(using: .utf8)!, withName: keyObj)
} else
if let num = element as? Int {
let value = "\(num)"
multipartFormData.append(value.data(using: .utf8)!, withName: keyObj)
}
})
}
}
if let data = imageData{
multipartFormData.append(data, withName: "file", fileName: "\(Date.init().timeIntervalSince1970).png", mimeType: "image/png")
}
},
to: endUrl, method: .post , headers: headers)
.responseJSON(completionHandler: { (response) in
print(response)
if let err = response.error{
print(err)
onError?(err)
return
}
print("Succesfully uploaded")
let json = response.data
if (json != nil)
{
let jsonObject = JSON(json!)
print(jsonObject)
}
})
}

Alamofire multipart upload giving error

I am trying to upload an image to server using Alamofire Multipart Form data however upon execution iam getting error as
exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber
dataUsingEncoding:]: unrecognized selector sent to instance
0x1669e250'
in the line
MultipartFormData.append(((value as AnyObject).data(using: String.Encoding.utf8.rawValue))!, withName: key)
below is my full code
guard let image = selectedImage else {
return
}
let heightInPixels = Int(image.size.height * image.scale)
let widthInPixels = Int(image.size.width * image.scale)
let parameters: Parameters = ["user_id": Utility().getBearerToken(),"description": descriptionTextView.text ?? "",
"lat": self.lat ?? "" , "long":self.long ?? "" ,
"location_name": locationTextView.text ?? "" ,
"height": heightInPixels, "width": widthInPixels];
// let parameters: Parameters = ["user_id": Utility().getBearerToken()];
print(parameters)
Alamofire.upload(multipartFormData: { MultipartFormData in
for (key, value) in parameters {
MultipartFormData.append(((value as AnyObject).data(using: String.Encoding.utf8.rawValue))!, withName: key)
}
let imgData = UIImageJPEGRepresentation(image,1)
MultipartFormData.append(imgData!, withName: "file", fileName: "upload.jpg", mimeType: "image/jpeg")
}, to: "http://server.com/upload.php") { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
print("Upload Progress: \(Progress.fractionCompleted)")
})
upload.responseString { response in
print(response.result.value!)
}
case .failure(let encodingError):
print(encodingError.localizedDescription)
break
}
}
I tried with MultipartFormData.append(value.data(using: .utf8)!, withName: name!) but it says value has no member data
Try this below func, it is working.
func uploadImage(urlString : String , image : UIImage, param : [String : Any], completionHandler : #escaping ( _ result : Any?) -> ()) {
guard let imageData = UIImageJPEGRepresentation(image, 0.5) else {
print("Could not get JPEG representation of UIImage")
return
}
Alamofire.upload(multipartFormData: { multipartFormData in
for (key, value) in param {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
multipartFormData.append(imageData,
withName: "image",
fileName: "image.jpg",
mimeType: "image/jpeg")
},
to: urlString,
headers: ["Authorization": "Basic xxx"],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress { progress in
}
upload.validate()
upload.responseJSON { response in
completionHandler(response.result.value)
}
case .failure(let encodingError):
print(encodingError)
completionHandler(nil)
}
})
}
Here is the function for upload video and image with your other API Parameters.
func uploadWithAlamofire(Parameters params : [String: Any]?,ImageParameters imgparams : [NSObject : AnyObject]?,VideoParameters vidoparam : [NSObject : AnyObject]?,Action action : NSString, success: #escaping (AnyObject) -> Void, failure: #escaping (AnyObject) -> Void)
{
var base_url = BASEURL
base_url.append(action as String)
print(base_url)
var headers : HTTPHeaders = [:]
if let token = UserDefaults.standard.value(forKey: "webToken"){
headers = ["JWT-Authorization": "Bearer \(token)"]
}
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: headers,
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)
var dictonary:NSDictionary?
if let data = responseString?.data(using: String.Encoding.utf8) {
do {
dictonary = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject] as NSDictionary?
if dictonary != nil{
if dictonary?.value(forKey: "status_code") as! String == "200"{
return success(dictonary!)
}else{
print(dictonary?.value(forKey: "status_code")! as Any)
let errorMsg : Any = Int(dictonary?.value(forKey: "status_code") as Any)
utility.showAlertWithStatusCode(code: errorMsg)
}
}
} catch let error as NSError {
print(error)
}
}
}
case .failure(let encodingError):
print("error:\(encodingError)")
return failure(encodingError as AnyObject)
}
})
}

How to send array in params using Alamofire multipart

I am using Alamofire for uploading image and file to the server. But I am facing issue to send an array in parameters with the image. But when I send an array in params it converts the array in JSON string. But I want to send an array in params, not JSON string. I have searched a lot and did not find any solution. So please tell me what's wrong in my code. I am using below code:
let params = ["id":"112","arrayParam":["1232","12344","14325"]]
let url = www.khxjjhdfsj.com/hsdgs
let headers: HTTPHeaders = [
/* "Authorization": "your_access_token", in case you need authorization header */
"Content-type": "multipart/form-data"
]
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in params
{
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = imageData
{
multipartFormData.append(data, withName: "file", fileName: fileName, mimeType: "image/png")
}
if let data = pdfData
{
multipartFormData.append(data, withName: "file", fileName: fileName, mimeType:"application/pdf")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded")
if let err = response.error
{
onError?(err)
return
}
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
onError?(error)
}
}
You need to pass image parameter along with your other request parameters. Pass your array parameters like this in below code:
Alamofire.upload(
multipartFormData: { multipartFormData in
// Pass your image parameter in imgObj
if let imageData = UIImageJPEGRepresentation(imgObj, 1) {
multipartFormData.append(UIImagePNGRepresentation(imgObj)!, withName: "profile_image", fileName: "THDC", mimeType: "image/png")
}
// Send other request parameters
for (key, value) in yourArray {
multipartFormData.append((value as! String).data(using: .utf8)!, withName: key)
}
},to: YourURL,headers:[:],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
SVProgressHUD.dismiss()
debugPrint("SUCCESS RESPONSE: \(response)")
if let dicObj = response.result.value as? NSDictionary {
print(dicObj)
}
}
case .failure(let encodingError):
SVProgressHUD.dismiss()
print("ERROR RESPONSE: \(encodingError)")
}
}
)
This is the static way to upload arrays to Alamofire.
hope this may useful to you.
Alamofire.upload(multipartFormData: { (multipartFormData) in
let imageData = UIImageJPEGRepresentation(imageUpload!, 0.5)
multipartFormData.append(imageData!, withName: "profile_file", fileName: "file.png", mimeType: "image/jpg")
for (key, value) in parameters {
if (value as AnyObject).isKind(of: NSMutableArray.self)
{
let arrayObj = value as! NSMutableArray
//let data2 = NSData(bytes: &arrayObj, length: arrayObj.count)
let count : Int = arrayObj.count
for i in 0 ..< count
{
let value = arrayObj[i] as! Int
let valueObj = String(value)
let keyObj = key + "[" + String(i) + "]"
multipartFormData.append(valueObj.data(using: String.Encoding.utf8)!, withName: keyObj)
}
}
else{
var valueStr = String()
if let param = value as? String{
valueStr = param
}else{
let valueInt = value as! Int
valueStr = String(valueInt)
}
multipartFormData.append((valueStr).data(using: String.Encoding.utf8)!, withName: key)
}
}
}, to: urlString, encodingCompletion: { (encodingResult) in
print("=====encodingResult=========",encodingResult)
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON(completionHandler: { (response) -> Void in
switch response.result {
case .success(let JSON):
print("JSON: \(JSON)")
onCompletion(JSON as? NSDictionary, nil)
case .failure(let error):
print(error)
}
})
case .failure(let encodingError):
print(encodingError);
}
})
You need to append array with multipart data on the same key required, like in your code you need to change only given line of code:
for (key, value) in params
{
// check the key on which key array is coming
if key == "arrayParam" {
let arrData = try! JSONSerialization.data(withJSONObject: value, options: .prettyPrinted)
multipartFormData.append(arrData, withName: key as String)
}
else {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}
Rest will be the same.

How to append array in multipart form data with Alamofire?

I am uploading image with multipart form data using Alamofire but getting some problem while i am passing an array as parameter.
As per request i need to pass all data into letter.
Here is how i am doing.
let data = try! JSONSerialization.data(withJSONObject: arrSelectedRecipientsID, options: .prettyPrinted)
let jsonString = String(data: data, encoding: .utf8)!
let paramArr : [String : Any] = [
"message" : txtvwMessage.text!,
"status": "draft",
"recipient_ids": jsonString
]
let parameter : [String : Any] = ["letter" : paramArr]
let accesstoken = Utilities.retriveValueFromDefault(forKey: UDKey.kUserAuthentication_Token) as String
let client = Utilities.retriveValueFromDefault(forKey: UDKey.kUserClient) as String
let uid = Utilities.retriveValueFromDefault(forKey: UDKey.kUserUID) as String
let headersInfo : HTTPHeaders = [ "Content-Type" : "multipart/form-data",
"Accept" : "application/json",
"access-token" : accesstoken,
"client" : client,
"uid" : uid
]
fileUploadWithParameter(Constant.ServerAPI.kPostLetters, images: letterImage, header: headersInfo, parameters: parameter, success: { (response) in
print(response)
}) { (progress) in
}
Here is Alamofire request method.
func fileUploadWithParameter(_ url: String,images:NSMutableArray,header : [String : String], parameters: [String:Any], success:#escaping (NSDictionary)->(),progressHandler:#escaping(_ progress: Double)->Void) {
Alamofire.upload(multipartFormData: { multipartFormData in
for i in 0..<images.count {
let rotatedImage = images[i] as! UIImage
if let imgData = UIImageJPEGRepresentation(rotatedImage, 0.8) {
multipartFormData.append(imgData, withName: "letter[photos]",fileName: "0\(i).jpg", mimeType: "image/jpg")
}
}
for (key, value) in parameters {
//multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key )
let paramsData:Data = NSKeyedArchiver.archivedData(withRootObject: value)
multipartFormData.append(paramsData, withName: key)
}
}, to: url,
method:.post,
headers:header) { (result) in
print("\n\n\nRequest URL :- \(url)\nParameters :- \(parameters)")
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
if response.error != nil {
print("Error :- \((response.error?.localizedDescription)!)\n\n\n")
}
if let jsonDict = response.result.value as? NSDictionary {
print("Response :- \(jsonDict)\n\n\n")
} else {
print("Error :- \(Constant.ErrorMessage.kCommanError)\n\n\n")
}
}
case .failure(let encodingError):
print("Error :- \(encodingError.localizedDescription)\n\n\n")
}
}
}
Postman works well so can someone please help me where i am doing wrong.
API expected The proper json should be
{
"letter":
{
"message": "Type your message here...!!!",
"recipient_ids": [183, 184],
"status": "draft"
}
}
API is in ruby on rails and it says i am sending string. Please help me to find out what is issue.
Jus need to change only given line of code:
for (key, value) in parameters {
if key == "letter" {
let arrData = try! JSONSerialization.data(withJSONObject: value, options: .prettyPrinted)
multipartFormData.append(arrData, withName: key as String)
}
else {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}
Rest will be the same.
your method in updated form:
func fileUploadWithParameter(_ url: String,images:NSMutableArray,header : [String : String], parameters: [String:Any], success:#escaping (NSDictionary)->(),progressHandler:#escaping(_ progress: Double)->Void) {
Alamofire.upload(multipartFormData: { multipartFormData in
for i in 0..<images.count {
let rotatedImage = images[i] as! UIImage
if let imgData = UIImageJPEGRepresentation(rotatedImage, 0.8) {
multipartFormData.append(imgData, withName: "letter[photos]",fileName: "0\(i).jpg", mimeType: "image/jpg")
}
}
for (key, value) in parameters {
//multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key )
let paramsData:Data = NSKeyedArchiver.archivedData(withRootObject: value)
multipartFormData.append(paramsData, withName: key)
}
for (key, value) in parameters {
if key == "letter" {
let arrData = try! JSONSerialization.data(withJSONObject: value, options: .prettyPrinted)
multipartFormData.append(arrData, withName: key as String)
}
else {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}
}, to: url,
method:.post,
headers:header) { (result) in
print("\n\n\nRequest URL :- \(url)\nParameters :- \(parameters)")
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
if response.error != nil {
print("Error :- \((response.error?.localizedDescription)!)\n\n\n")
}
if let jsonDict = response.result.value as? NSDictionary {
print("Response :- \(jsonDict)\n\n\n")
} else {
//print("Error :- \(Constant.ErrorMessage.kCommanError)\n\n\n")
print("Errfdc")
}
}
case .failure(let encodingError):
print("Error :- \(encodingError.localizedDescription)\n\n\n")
}
}
}
Finally get it done with separate append in request. Here is how you can pass an array in multipart form data request.
Alamofire.upload(multipartFormData: { multipartFormData in
for i in 0..<self.letterImage.count {
let rotatedImage = self.letterImage[i] as! UIImage
if let imgData = UIImageJPEGRepresentation(rotatedImage, 0.8) {
multipartFormData.append(imgData, withName: "letter[photos][]",fileName: "0\(i).jpg", mimeType: "image/jpg")
}
}
multipartFormData.append("\(message)".data(using: String.Encoding.utf8)!, withName: "letter[message]")
multipartFormData.append("draft".data(using: String.Encoding.utf8)!, withName: "letter[status]")
for (_,value) in self.arrSelectedRecipientsID.enumerated() {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: "letter[recipient_ids][]")
}
}
you can append array of like below
for image attachments
for Attachment in Attachments
{
if let pic = Attachment{
let randome = arc4random()
let data = UIImageJPEGRepresentation(pic, 0.8)
MultipartFormData.append(data!, withName: "letter[photos][]", fileName: "randome\(randome).jpg", mimeType: "image/jpg")
}
}
for parameters
for (key,value) in params
{
MultipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: "\(key)")
}

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

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?
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
}
})
}
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.
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)
}

Resources