How to send array in params using Alamofire multipart - ios

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.

Related

Alamofire multipartFormData using [String : Any] parameters

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...

how to upload image,pdf,audio,video and any file system from iphone local memory to server(API)

I have to upload any kind of file system from local phone memory to API given.Is there a simple way to that please help.
You can use Alamofire library.
https://github.com/Alamofire/Alamofire
Alamofire.upload(multipartFormData: { (multipartFormData) in
if let parameters = parameters {
for (key, value) in parameters {
if let value = value as? String {
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}else if let _image = value as? UIImage, let image = _image.resized(toWidth: 500) {
if let jpegData = image.jpegData(compressionQuality: 0.5) {
multipartFormData.append(jpegData, withName: key, fileName: "post.jpeg", mimeType: "image/jpeg")
}else if let pngData = image.pngData() {
multipartFormData.append(pngData, withName: key, fileName: "post.png", mimeType: "image/jpeg")
}
}else {
multipartFormData.append(Data(from: value), withName: key)
}
}
}
}, usingThreshold: UInt64.init(), to: urlString, method: method, headers: headers, encodingCompletion: { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
if let responseData = response.result.value as? NSDictionary {
completion(responseData, response.data, response.result)
}else if let responseData = response.result.value as? [String: Any] {
completion(responseData as NSDictionary, response.data, response.result)
}else {
completion([:], nil, response.result)
}
}
break
case .failure(let encodingError):
completion([:], nil, .failure(encodingError))
break
}
})

how to append String Array to form data

I want to send file with other parameters.I was able to send that using alamofire upload.but the question is in my parameters i have String arrays.I dont know how to append them in to form data.
let parameters = ["comments":comments!,
"title":title!,
"publish_date":publish_date,
"expiry_date":expiry_date,
"visibility[staff]":"N",
"visibility[students][Forms]":["1","2"]
]
]
as [String : Any]
let headers = [
"Content-type": "multipart/form-data"
]
let URL_head = try! URLRequest(url: STAFF_SERVICE_URL + "staff/2/news?api_key=\(api_key)", method: .post, headers: headers)
Alamofire.upload(multipartFormData: { (multipartFormData) in
if let url = fileUrl{
multipartFormData.append(url, withName: "file")
}
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
print(multipartFormData)
}, with:URL_head)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
NSLog("Upload response \(response)")
if let jsonValue = response.result.value {
_ = JSON(jsonValue)
completion(true ,"Suucess")
}else{
completion(false ,"Error")
}
}
case .failure(let encodingError):
print("fail \(encodingError)")
NSLog("Error \(result)")
completion(false ,"No Internet")
}
}
}
i tried to encode array seperately like this.but not worked.
let data = try! JSONSerialization.data(withJSONObject: array,
options:.prettyPrinted)
let jsonString = String(data: data, encoding: .utf8)!
You can directly pass data object you don't need to convert back to string
for example
for (key, value) in parameters {
if checkIfItIsArray {
// Make sure you handle error here
let data = try! JSONSerialization.data(withJSONObject: array, options:nil)
multipartFormData.append(data, withName: key as String)
} else {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}

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

Send POST parameters with MultipartFormData using Alamofire, in iOS Swift

I am using Alamofire, very first time. I am using the latest version Alamofire 1.3.1. I want to send one image , one video and some POST parameters in one API call. I am using multipart form data. The mutipart module is working. I am facing a problem to send extra POST parametersparams . Below is my code. "params" is the dictionary which contains extra parameters? How can I append these POST parameters in the request. Please help
var fullUrl :String = Constants.BASE_URL + "/api/CompleteChallenge"
var params = [
"authKey": Constants.AuthKey,
"idUserChallenge": "16",
"comment": "",
"photo": imagePath,
"video": videoPath,
"latitude": "1",
"longitude": "1",
"location": "india"
]
let imagePathUrl = NSURL(fileURLWithPath: imagePath!)
let videoPathUrl = NSURL(fileURLWithPath: videoPath!)
Alamofire.upload(
.POST,
URLString: fullUrl, // http://httpbin.org/post
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(fileURL: imagePathUrl!, name: "photo")
multipartFormData.appendBodyPart(fileURL: videoPathUrl!, name: "video")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { request, response, JSON, error in
}
}
case .Failure(let encodingError):
}
}
)
I found the solution :) finally.
We can append data in the request as multipartformdata.
Below is my code.
Alamofire.upload(
.POST,
URLString: fullUrl, // http://httpbin.org/post
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(fileURL: imagePathUrl!, name: "photo")
multipartFormData.appendBodyPart(fileURL: videoPathUrl!, name: "video")
multipartFormData.appendBodyPart(data: Constants.AuthKey.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"authKey")
multipartFormData.appendBodyPart(data: "\(16)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"idUserChallenge")
multipartFormData.appendBodyPart(data: "comment".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"comment")
multipartFormData.appendBodyPart(data:"\(0.00)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"latitude")
multipartFormData.appendBodyPart(data:"\(0.00)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"longitude")
multipartFormData.appendBodyPart(data:"India".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"location")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { request, response, JSON, error in
}
case .Failure(let encodingError):
}
}
)
EDIT 1: For those who are trying to send an array instead of float, int or string, They can convert their array or any kind of data-structure in Json String, pass this JSON string as a normal string. And parse this json string at backend to get original array
In Alamofire 4 it is important to add the body data before you add the file data!
let parameters = [String: String]()
[...]
self.manager.upload(
multipartFormData: { multipartFormData in
for (key, value) in parameters {
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}
multipartFormData.append(imageData, withName: "user", fileName: "user.jpg", mimeType: "image/jpeg")
},
to: path,
[...]
)
This is how i solve my problem
let parameters = [
"station_id" : "1000",
"title": "Murat Akdeniz",
"body": "xxxxxx"]
let imgData = UIImageJPEGRepresentation(UIImage(named: "1.png")!,1)
Alamofire.upload(
multipartFormData: { MultipartFormData in
// multipartFormData.append(imageData, withName: "user", fileName: "user.jpg", mimeType: "image/jpeg")
for (key, value) in parameters {
MultipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
MultipartFormData.append(UIImageJPEGRepresentation(UIImage(named: "1.png")!, 1)!, withName: "photos[1]", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
MultipartFormData.append(UIImageJPEGRepresentation(UIImage(named: "1.png")!, 1)!, withName: "photos[2]", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
}, to: "http://platform.twitone.com/station/add-feedback") { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
print(response.result.value)
}
case .failure(let encodingError): break
print(encodingError)
}
}
Swift 3 / Alamofire 4.0 (Addendum to the accepted answer)
To append to multipartFormData in Swift 3 / Alamofire 4.0, use the following method of MultipartFormData:
public func append(_ data: Data, withName name: String) { /* ... */ }
And, to convert String to Data, the data(using:) method of String. E.g.,
multipartFormData.append("comment".data(using: .utf8)!, withName: "comment")
For Swift 4.2 / Alamofire 4.7.3
Alamofire.upload(multipartFormData: { multipart in
multipart.append(fileData, withName: "payload", fileName: "someFile.jpg", mimeType: "image/jpeg")
multipart.append("comment".data(using: .utf8)!, withName :"comment")
}, to: "endPointURL", method: .post, headers: nil) { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.response { answer in
print("statusCode: \(answer.response?.statusCode)")
}
upload.uploadProgress { progress in
//call progress callback here if you need it
}
case .failure(let encodingError):
print("multipart upload encodingError: \(encodingError)")
}
}
Also you could take a look at CodyFire lib it makes API calls easier using Codable for everything.
Example for Multipart call using CodyFire
//Declare your multipart payload model
struct MyPayload: MultipartPayload {
var attachment: Attachment //or you could use just Data instead
var comment: String
}
// Prepare payload for request
let imageAttachment = Attachment(data: UIImage(named: "cat")!.jpeg(.high)!,
fileName: "cat.jpg",
mimeType: .jpg)
let payload = MyPayload(attachment: imageAttachment, comment: "Some text")
//Send request easily
APIRequest("endpoint", payload: payload)
.method(.post)
.desiredStatus(.created) //201 CREATED
.onError { error in
switch error.code {
case .notFound: print("Not found")
default: print("Another error: " + error.description)
}
}.onSuccess { result in
print("here is your decoded result")
}
//Btw normally it should be wrapped into an extension
//so it should look even easier API.some.upload(payload).onError{}.onSuccess{}
You could take a look at all the examples in lib's readme
Alamofire 5 and above
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(Data("one".utf8), withName: "one")
multipartFormData.append(Data("two".utf8), withName: "two")
},
to: "https://httpbin.org/post").responseDecodable(of: MultipartResponse.self) { response in
debugPrint(response)
}
documentation link: multipart upload
Swift 5, update #Ankush's Alamofire Code to
var fullUrl = "http://httpbin.org/post" // for example
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append( imagePathUrl! , withName: "photo")
multipartFormData.append( videoPathUrl!, withName: "video")
multipartFormData.append(Constants.AuthKey.data(using: .utf8, allowLossyConversion: false)!, withName: "authKey")
multipartFormData.append("16".data(using: .utf8, allowLossyConversion: false)!, withName: "idUserChallenge")
multipartFormData.append("111".data(using: .utf8, allowLossyConversion: false)!, withName: "authKey")
multipartFormData.append("comment".data(using: .utf8, allowLossyConversion: false)!, withName: "comment")
multipartFormData.append("0.00".data(using: .utf8, allowLossyConversion: false)!, withName: "latitude")
multipartFormData.append("0.00".data(using: .utf8, allowLossyConversion: false)!, withName: "longitude")
multipartFormData.append("India".data(using: .utf8, allowLossyConversion: false)!, withName: "location")
}, to: fullUrl, method: .post) { (encodingResult) in
switch encodingResult {
case .success(request: let upload, streamingFromDisk: _, streamFileURL: _):
upload.responseJSON { (response) in // do sth }
case .failure(let encodingError):
()
}
}
As in Swift 3.x for upload image with parameter we can use below alamofire upload method-
static func uploadImageData(inputUrl:String,parameters:[String:Any],imageName: String,imageFile : UIImage,completion:#escaping(_:Any)->Void) {
let imageData = UIImageJPEGRepresentation(imageFile , 0.5)
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imageData!, withName: imageName, fileName: "swift_file\(arc4random_uniform(100)).jpeg", mimeType: "image/jpeg")
for key in parameters.keys{
let name = String(key)
if let val = parameters[name!] as? String{
multipartFormData.append(val.data(using: .utf8)!, withName: name!)
}
}
}, to:inputUrl)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
})
upload.responseJSON { response in
if let JSON = response.result.value {
completion(JSON)
}else{
completion(nilValue)
}
}
case .failure(let encodingError):
completion(nilValue)
}
}
}
Note: Additionally if our parameter is array of key-pairs then we can
use
var arrayOfKeyPairs = [[String:Any]]()
let json = try? JSONSerialization.data(withJSONObject: arrayOfKeyPairs, options: [.prettyPrinted])
let jsonPresentation = String(data: json!, encoding: .utf8)
Well, since Multipart Form Data is intended to be used for binary ( and not for text) data transmission, I believe it's bad practice to send data in encoded to String over it.
Another disadvantage is impossibility to send more complex parameters like JSON.
That said, a better option would be to send all data in binary form, that is as Data.
Say I need to send this data
let name = "Arthur"
let userIDs = [1,2,3]
let usedAge = 20
...alongside with user's picture:
let image = UIImage(named: "img")!
For that I would convert that text data to JSON and then to binary alongside with image:
//Convert image to binary
let data = UIImagePNGRepresentation(image)!
//Convert text data to binary
let dict: Dictionary<String, Any> = ["name": name, "userIDs": userIDs, "usedAge": usedAge]
userData = try? JSONSerialization.data(withJSONObject: dict)
And then, finally send it via Multipart Form Data request:
Alamofire.upload(multipartFormData: { (multiFoormData) in
multiFoormData.append(userData, withName: "user")
multiFoormData.append(data, withName: "picture", mimeType: "image/png")
}, to: url) { (encodingResult) in
...
}
for alamofire 4 use this ..
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(fileUrl, withName: "video")
//fileUrl is your file path in iOS device and withName is parameter name
}, to:"http://to_your_url_path")
{ (result) in
switch result {
case .success(let upload, _ , _):
upload.uploadProgress(closure: { (progress) in
print("uploding")
})
upload.responseJSON { response in
print("done")
}
case .failure(let encodingError):
print("failed")
print(encodingError)
}
}
Found one more way of doing it
if let parameters = route.parameters {
for (key, value) in parameters {
if value is String {
if let temp = value as? String {
multipartFormData.append(temp.description.data(using: .utf8)!, withName: key)
}
}
else if value is NSArray {
if let temp = value as? [Double]{
multipartFormData.append(temp.description.data(using: .utf8)!, withName: key)
}
else if let temp = value as? [Int]{
multipartFormData.append(temp.description.data(using: .utf8)!, withName: key)
}
else if let temp = value as? [String]{
multipartFormData.append(temp.description.data(using: .utf8)!, withName: key)
}
}
else if CFGetTypeID(value as CFTypeRef) == CFNumberGetTypeID() {
if let temp = value as? Int {
multipartFormData.append(temp.description.data(using: .utf8)!, withName: key)
}
}
else if CFGetTypeID(value as CFTypeRef) == CFBooleanGetTypeID(){
if let temp = value as? Bool {
multipartFormData.append(temp.description.data(using: .utf8)!, withName: key)
}
}
}
}
if let items: [MultipartData] = route.multipartData{
for item in items {
if let value = item.value{
multipartFormData.append(value, withName: item.key, fileName: item.fileName, mimeType: item.mimeType)
}
}
}
Alamofire 5 with Array params
The issue for me was that my params could be any type. Converting to them to strings and then getting the data encoding worked for most, but I kept running into issues with arrays. For arrays you have to encode each element with a key denoting its index. This is how I ended up encoding my params so it would be dynamic for any type:
let image = UIImage(named: "your image") // Change me
let imageData = image.jpegData(compressionQuality: 1.0)!
let imageKey = "image_key" // Change me
let urlString = "https://yourserver.com/yourendpoint/" // Change me
let params: [String: Any]? = [:] // Change me. Your POST params here
let headers: HTTPHeaders = [
// Change me. Your headers here.
]
AF.upload(multipartFormData: { multiPart in
for (key, value) in (params ?? [:]) {
if let arrayObj = value as? [Any] {
for index in 0..<arrayObj.count {
multiPart.append("\(arrayObj[index])".data(using: .utf8)!, withName: "\(key)[\(index)]")
}
} else {
multiPart.append("\(value)".data(using: .utf8)!, withName: key)
}
}
multiPart.append(imageData, withName: imageKey, fileName: "file.jpg", mimeType: "image/jpg")
}, to: urlString, headers: headers).responseJSON { response in
switch response.result {
case .success(_):
if let dictionary = response.value as? [String:Any] {
print("success", dictionary)
} else {
print("error")
}
case .failure(let error):
print("error", error.localizedDescription)
}
}
Also note that you have to append the image after appending all your params
func funcationname()
{
var parameters = [String:String]()
let apiToken = "Bearer \(UserDefaults.standard.string(forKey: "vAuthToken")!)"
let headers = ["Vauthtoken":apiToken]
let mobile = "\(ApiUtillity.sharedInstance.getUserData(key: "mobile"))"
parameters = ["first_name":First_name,"last_name":last_name,"email":Email,"mobile_no":mobile]
print(parameters)
ApiUtillity.sharedInstance.showSVProgressHUD(text: "Loading...")
let URL1 = ApiUtillity.sharedInstance.API(Join: "user/update_profile")
let url = URL(string: URL1.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = headers
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(self.imageData_pf_pic, withName: "profile_image", fileName: "image.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, with: urlRequest) { (encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)")
let status = (JSON as AnyObject).value(forKey: "status") as! Int
let sts = Int(status)
if sts == 200
{
ApiUtillity.sharedInstance.dismissSVProgressHUD()
let UserData = ((JSON as AnyObject).value(forKey: "data") as! NSDictionary)
ApiUtillity.sharedInstance.setUserData(data: UserData)
}
else
{
ApiUtillity.sharedInstance.dismissSVProgressHUD()
let ErrorDic:NSDictionary = (JSON as AnyObject).value(forKey: "message") as! NSDictionary
let Errormobile_no = ErrorDic.value(forKey: "mobile_no") as? String
let Erroremail = ErrorDic.value(forKey: "email") as? String
if Errormobile_no?.count == nil
{}
else
{
ApiUtillity.sharedInstance.dismissSVProgressHUDWithError(error: Errormobile_no!)
}
if Erroremail?.count == nil
{}
else
{
ApiUtillity.sharedInstance.dismissSVProgressHUDWithError(error: Erroremail!)
}
}
}
}
case .failure(let encodingError):
ApiUtillity.sharedInstance.dismissSVProgressHUD()
print(encodingError)
}
}
}

Resources