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)
}
})
}
Related
func uploadImage(image: UIImage, imageUrl: String, imageExtension: String , responseData: #escaping (_ response: UploaderModel)-> ()) {
var status : UploaderModel?
let token = UserDefaults.standard.string(forKey: PrefKeys.loginToken) ?? ""
let authorization = ["Authorization" : "Bearer \(token)"]
let imageURl = "http://68.183.152.132/api/v1/stuff/uploader"
//Parameter HERE
let parameters = [
"garbageCollector": 0,
"stuff_uuid": "2b4b750a-f4a6-4d61-84ce-7c42b5c030ee",
"delete_file" : ""
] as [String : Any]
//Header HERE
let headers: HTTPHeaders
headers = ["Content-type": "multipart/form-data",
"Content-Disposition" : "form-data"]
guard let imgData = firstImage.image?.jpegData(compressionQuality: 0.7) else { return }
AF.upload(multipartFormData: { multipartFormData in
//Parameter for Upload files
multipartFormData.append(imgData, withName: "file",fileName: imageUrl , mimeType: "image/\(imageExtension)")
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
}, usingThreshold:UInt64.init(),
to: imageURl, //URL Here
method: .post,
headers: headers, //pass header dictionary here
interceptor: { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Uploading")
})
upload.responseJSON { response in
print("the resopnse code is : \(response.response?.statusCode)")
print("the response is : \(response.description)")
let json = JSON(response.data)
if let msg = json["msg"].string {
status.msg = msg
}
if let stat = json["status"].int {
status.status = stat
}
responseData(status)
}
break
case .failure(let encodingError):
print("the error is : \(encodingError.localizedDescription)")
break
}
} )
}
error : Cannot convert value of type '(_) -> ()' to expected argument type 'RequestInterceptor?'
A little bit cleaner look solution of Vishal Darvara asnwer for Alamofire 5 .
func uploadPhoto(_ url: String, image: UIImage, params: [String : Any], header: [String:String], completion: #escaping (JSON) -> ()) {
let httpHeaders = HTTPHeaders(header)
AF.upload(multipartFormData: { multiPart in
for p in params {
multiPart.append("\(p.value)".data(using: String.Encoding.utf8)!, withName: p.key)
}
multiPart.append(image.jpegData(compressionQuality: 0.4)!, withName: "avatar", fileName: "file.jpg", mimeType: "image/jpg")
}, to: url, method: .post, headers: httpHeaders) .uploadProgress(queue: .main, closure: { progress in
print("Upload Progress: \(progress.fractionCompleted)")
}).responseJSON(completionHandler: { data in
print("upload finished: \(data)")
}).response { (response) in
switch response.result {
case .success(let resut):
print("upload success result: \(resut)")
case .failure(let err):
print("upload err: \(err)")
}
}
}
//swift 5
static func postComplexPictures(url:URL, params:[String:Any],pictures : UIImage, finish: #escaping ((message:String, list:[[String: Any]],isSuccess:Bool)) -> Void) {
var result:(message:String, list:[[String: Any]],isSuccess:Bool) = (message: "Fail", list:[],isSuccess : false)
let headers: HTTPHeaders
headers = ["Content-type": "multipart/form-data",
"Content-Disposition" : "form-data"]
AF.upload(multipartFormData: { (multipartFormData) in
for (key, value) in params {
multipartFormData.append((value as! String).data(using: String.Encoding.utf8)!, withName: key)
}
if let imageData = pictures.pngData() {
multipartFormData.append(imageData, withName: "document", fileName: "document.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers).response{ response in
if((response.error != nil))
{
do
{
if let jsonData = response.data
{
let parsedData = try JSONSerialization.jsonObject(with: jsonData) as! Dictionary<String, AnyObject>
print(parsedData)
let status = parsedData["status"] as? NSInteger ?? 0
let msg = parsedData["message"] as? String ?? ""
if(status==1)
{
result.isSuccess = true
result.message=msg
if let jsonArray = parsedData["data"] as? [[String: Any]] {
result.list=jsonArray
}
}
else
{
result.isSuccess = false
result.message=msg
}
}
finish(result)
}
catch
{
finish(result)
}
}
else
{
finish(result)
}
}
}
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)
}
})
}
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.
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)
}
I am stuck in uploading multiple images in multipart using Alamofire. Can any one help me?
Thanks in advance!!
For more details, I am using this code to create body part of images data:
func imageArrayToNSData(array: [UIImage],boundary:String) -> NSData {
let body = NSMutableData()
var i = 0;
for image in array{
let filename = "image\(i).jpg"
let data = UIImageJPEGRepresentation(image,0.8);
let mimetype = "image/jpeg"
let key = "product_images"
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(filename)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: \(mimetype)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(data!)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
i += 1
}
body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
return body
}
to upload I am using :
Alamofire.upload(.POST, EDIT_PRODUCT_URL, headers: ["Accept": "application/json","Content-Type":"application/json"], multipartFormData: { (formData) in
if productImages.count>0{
let boundary = generateBoundaryString()
let imageData = CommonClass.imageArrayToNSData(productImages,boundary: boundary)
formData.appendBodyPart(data: imageData, name: "product_images", mimeType: "image/jpeg")
}
for (key, value) in params {
if value is [String]{
let data = CommonClass.stringArrayToNSData(value as! [String])
formData.appendBodyPart(data:data , name: key)
}else if value is String{
formData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}else if let v = value as? Bool{
var bValue = v
let d = NSData(bytes: &bValue, length: sizeof(Bool))
formData.appendBodyPart(data: d, name: key)
}
}
}) { (encodingResult) in
switch encodingResult {
case .Success(let upload, _, _):
KVNProgress.showProgress(CGFloat(0), status:"0% Sent")
upload.progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
// This closure is NOT called on the main queue for performance
// reasons. To update your ui, dispatch to the main queue.
dispatch_async(dispatch_get_main_queue()) {
let prg = Int((CGFloat(totalBytesWritten)*100)/CGFloat(totalBytesExpectedToWrite))
if prg == 100{
KVNProgress.showSuccessWithStatus("Created")
}
KVNProgress.updateStatus("\(prg)% Sent")
KVNProgress.updateProgress(CGFloat(Float(prg)/100.0), animated: true)
}
}
upload.responseJSON { response in
CommonClass.hideLoader()
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
print_debug("edit Product JSON is\n\(json)");
completionBlock(json)
}else{
completionBlock(nil)
}
case .Failure(let error):
print_debug(error.description)
showErrorWithMessage("Oops! Couldn't connect to server!")
completionBlock(nil)
}
}
case .Failure(let encodingError):
print(encodingError)
}
}
Can any one please let me suggest the way to upload multiple files in multipart using Alamofire?
In Swift 3 and above
Just append "[]" with image key identifier to treat it as array of images.
Alamofire.upload(multipartFormData: { multipartFormData in
// import image to request
for imageData in imagesData {
multipartFormData.append(imageData, withName: "\(imageParamName)[]", fileName: "\(Date().timeIntervalSince1970).jpeg", mimeType: "image/jpeg")
}
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
}, to: urlString,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
}
case .failure(let error):
print(error)
}
})
I Hope it will be helpful for you:
Using Swift 3x: (I have uploaded four Photos in this snippet)
//MARK: - upload multiple photos
func uploadImagesAndData(params:[String : AnyObject]?,image1: UIImage,image2: UIImage,image3: UIImage,image4: UIImage,headers : [String : String]?, completionHandler:#escaping CompletionHandler) -> Void {
let imageData1 = UIImageJPEGRepresentation(image1, 0.5)!
let imageData2 = UIImageJPEGRepresentation(image2, 0.5)!
let imageData3 = UIImageJPEGRepresentation(image3, 0.5)!
let imageData4 = UIImageJPEGRepresentation(image4, 0.5)!
Alamofire.upload(multipartFormData: { multipartFormData in
for (key, value) in params! {
if let data = value.data(using: String.Encoding.utf8.rawValue) {
multipartFormData.append(data, withName: key)
}
}
multipartFormData.append(imageData1, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
multipartFormData.append(imageData2, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
multipartFormData.append(imageData3, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
multipartFormData.append(imageData4, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
},
to: K_BASEURL + K_API_LOGINDATA, encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload
.validate()
.responseJSON { response in
switch response.result {
case .success(let value):
print("responseObject: \(value)")
case .failure(let responseError):
print("responseError: \(responseError)")
}
}
case .failure(let encodingError):
print("encodingError: \(encodingError)")
}
})
}
1) To upload multiple image using Alamofire in Swift3
typealias APICompletionHandler = (code:Int, error:NSError?, response:AnyObject?) -> Void
func uploadIMultipart(_ strApiName:String, param : NSDictionary?, data:Array<NSDictionary>, header:[String : String]?, completionHandler:#escaping APICompletionHandler)
{
let strURL : String = strApiName
let apiURL = try! URLRequest(url: strURL, method: .post, headers: header)
Alamofire.upload(multipartFormData: { (multipartFormData) in
// code
var i : Int = 0
for dict:NSDictionary in data {
let extention = dict["format"] as? String
let strMimeType = dict["strMimeType"] as? String
let nameofFile:String = (6.randomString as String)+"."+extention!
if (dict["data"] as? Data != nil) {
multipartFormData.append(Foundation.Data(dict["data"] as! Data), withName: dict["key"] as! String, fileName: nameofFile , mimeType: strMimeType!)
} else {
let strUrl = dict["data"] as! String
let fileURL : URL? = URL(string: strUrl)
multipartFormData.append(try! Foundation.Data(contentsOf: fileURL!), withName: dict["key"] as! String, fileName: nameofFile , mimeType: strMimeType!)
}
i += 1
}
for (key, value) in param! {
multipartFormData.append((value as! NSString).data(using: String.Encoding.utf8.rawValue)!, withName: key as! String)
}
}, with: apiURL, encodingCompletion: { (result) in
// code
switch result {
case .success(let upload,_ ,_ ):
upload.responseJSON { response in
switch response.result {
case .success(let data):
//Sucess
case .failure(let error):
print(error.localizedDescription)
}
}
case .failure(let encodingError):
print(encodingError)
completionHandler(0, encodingError as NSError?, nil)
}
})
}
2) To call Function
let imageData : NSData = UIImagePNGRepresentation(imgUserProfile.image!)! as NSData
let imageData1 : NSData = UIImagePNGRepresentation(imgUserProfile.image!)! as NSData
let dict1: Dictionary = ["data":imageData,"key":"user_image", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
let dict2: Dictionary = ["data":imageData1,"key":"image1", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
let array: Array = [dict1,dict2]; //pass this image array
self.uploadIMultipart(strAPI, param: dictParam as NSDictionary, data: array as Array<NSDictionary>, header: nil) { (code, error, response) in
AppSingletonObj.stopLoading(inView: self.view)
//API manager sucess or failure
if code == 1 {
let status = response?["success"]
//API sucess or failure
if(status as! Int == 1) {
print(response!)
}
else {
let errorMessage = response?["message"]
AppSingletonObj.showAlert(msg: errorMessage as! String)
}
}
else {
AppSingletonObj.showAlert(msg: "Some error occured! please try after sometime")
}
}
3) Extension to create file name
//MARK: CREATE RANDOM STRING of LENGTH
extension Int{
var randomString : String {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: self)
for _ in 0 ..< self{
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.character(at: Int(rand)))
}
return randomString as String
}
}
To upload multiple image you need to call this code in loop
let boundary = generateBoundaryString()
let imageData = CommonClass.imageArrayToNSData(productImages,boundary: boundary)
formData.appendBodyPart(data: imageData, name: "product_images", mimeType: "image/jpeg")
Swift 4.2.
Here code is only for without any parameters.
If you need to pass extra parameters just go with #Hardik Thakkar code.
typealias APICompletionHandler = (code:Int, error:NSError?, response:AnyObject?) -> Void
#IBOutlet weak var thirdImage: UIImageView!
var fristImage:UIImage = UIImage()
var secondimage:UIImage = UIImage()
extension ViewController {
func upload() {
let imgData1 = fristImage.jpegData(compressionQuality: 0.7)
let imgData2 = secondimage.jpegData(compressionQuality: 0.7)
let imgData3 = thirdImage.image!.jpegData(compressionQuality: 0.7)
let headers = [
"Authorization" : "Bearer " + "Your Token",
"Content-type": "form-data",
]
let dict1: Dictionary = ["data":imgData1 as Any,"key":"Here Your Body Key1", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
let dict2: Dictionary = ["data":imgData2 as Any,"key":"Here Your Body Key2", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
let dict3: Dictionary = ["data":imgData3 as Any,"key":"Here Your Body Key3", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
let array: Array = [dict1, dict2, dict3]; //pass this image array
self.uploadIMultipart("Here Your URL", data: array as Array<NSDictionary>, header: headers) { (code, error, response) in
let httpResponse = response as? HTTPURLResponse
print("the resopnse code is : \(String(describing: httpResponse?.statusCode.description))")
}
}
func uploadIMultipart(_ strApiName:String, data:Array<NSDictionary>, header:[String : String]?, completionHandler:#escaping APICompletionHandler) {
let strURL : String = strApiName
let apiURL = try! URLRequest(url: strURL, method: .post, headers: header)
Alamofire.upload(multipartFormData: { (multipartFormData) in
// code
var i : Int = 0
for dict:NSDictionary in data {
let extention = dict["format"] as? String
let strMimeType = dict["strMimeType"] as? String
let nameofFile:String = (6.randomString as String)+"."+extention!
if (dict["data"] as? Data != nil) {
multipartFormData.append(Foundation.Data(dict["data"] as! Data), withName: dict["key"] as! String, fileName: nameofFile , mimeType: strMimeType!)
} else {
let strUrl = dict["data"] as! String
let fileURL : URL? = URL(string: strUrl)
multipartFormData.append(try! Foundation.Data(contentsOf: fileURL!), withName: dict["key"] as! String, fileName: nameofFile , mimeType: strMimeType!)
}
i += 1
}
}, with: apiURL, encodingCompletion: { (result) in
// code
switch result {
case .success(let upload,_ ,_ ):
upload.responseJSON { response in
switch response.result {
case .success(let response):
//Sucess
print("response :-", response)
case .failure(let error):
//Failure
print(error.localizedDescription)
}
}
case .failure(let encodingError):
print(encodingError)
completionHandler(0, encodingError as NSError?, nil)
}
})
}
}
extension Int{
var randomString : String {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: self)
for _ in 0 ..< self{
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.character(at: Int(rand)))
}
return randomString as String
}
}
class func uploadImageToServer(uploadTo: String, imageParameters:[[String: Any]], otherParameters:[String: Any],authorization: String, completionHandler:#escaping ((_ responseValue: Any?, _ error: Error?) -> Void)) {
if isNetWorkAvailable() {
var urlRequest = URLRequest(url: URL.init(string: uploadTo)!)
urlRequest.httpMethod = "POST"
urlRequest.addValue(authorization, forHTTPHeaderField: "Authorization")
DispatchQueue.main.async(execute: {
ActivityIndicatorView.showActivity()
})
print("Request Url: \(uploadTo)\nRequest Params: \(imageParameters)\nRequest Params: \(otherParameters)")
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key,value) in otherParameters {
multipartFormData.append((value as! String).data(using: .utf8)!, withName: key)
}
for value in imageParameters {
let image = value["image"] as! UIImage
let imgData = UIImageJPEGRepresentation(image, 1)!
let imageName = value["imageName"] as! String
let fileName = value["fileName"] as! String
multipartFormData.append(imgData, withName: imageName, fileName: fileName ,mimeType: "image/jpeg")
}
}, usingThreshold: UInt64.init(), with: urlRequest, encodingCompletion: { (encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
let uploadPercetange = Int(progress.fractionCompleted*100)
print("Upload Progress: \(uploadPercetange)%")
})
upload.responseJSON(completionHandler: { (response) in
print(response.result.value ?? "NaN")
let result = response.result.value
completionHandler(result, nil)
DispatchQueue.main.async(execute: {
ActivityIndicatorView.hideActivity()
})
})
case .failure(let encodingError):
print(encodingError)
let error = encodingError
completionHandler(nil, error)
DispatchQueue.main.async(execute: {
ActivityIndicatorView.hideActivity()
})
}
})
} else {
AlertView.showAlert(title: "Error", message: "Network not available")
}
}