How to upload pictures with Alamofire (post)? - swift

I have to make an API request to upload an image which's whether been taken by the camera or picked from the gallery. The method set in the API is set and in the body/parameters there's only
key:file
value: //
where the value is the picture itself. (in postman I just upload a picture from my files and it works) and it returns an URL with some other information.
The issue is I can't get the request to have a successful response, and I don't know how I can pass the UIImage to Alamofire.
This is what I have done
Alamofire.request(baseUrl,
method: .post,
parameters: ["file" : expenseImage])
.responseJSON(completionHandler: { response in
guard response.result.error == nil else {
print("Error subiendo la imagen \n\(response.result.error!)")
return
}
guard let json = response.result.value as? [String: Any] else {
if let error = response.result.error {
print("Error: \(error.localizedDescription)")
}
return
}
do {
let decoder = JSONDecoder()
let rawData = try JSONSerialization.data(withJSONObject: json, options: [])
let dataObject = try decoder.decode(PutObjectFile.self, from: rawData)
finished(dataObject)
print(dataObject)
print(dataObject.msg.file_info.url)
} catch let error {
print("Error decoding:\n\(error)")
}
})
and the error I'm getting in the console is the following:
responseSerializationFailed(reason: Alamofire.AFError
.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
I tried using a random picture url but it doesn't work either

You can upload images using multipart data, Use below code:
let manager = Alamofire.SessionManager.default
do{
manager.upload(multipartFormData: { (formData) in
if let fileData = fileData { // File data
formData.append(fileData, withName: "FILE_NAME", fileName: "simple.jpeg", mimeType: "image/jpeg")
}
}, to: "API_PATH", method: HTTPMethod.post, headers: nil, encodingCompletion: { encoding in
switch encoding{
case .success(let req, _, _):
req.uploadProgress(closure: { (prog) in
progress?(prog)
}).responseJSON { (resObj) in
switch resObj.result{
case .success:
if let resData = resObj.data{
do {
let res = try JSONSerialization.jsonObject(with: resData)
print(res) // Success
} catch let err{
print(err)
}
}
break
case .failure(let err):
print(err)
break
}
}
break
case .failure(let err):
print(err)
break
}
})
}catch let err{
print(err)
}

I had the same problem, I've solved it doing this:
Alamofire 5.0.0-beta.5
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "file",fileName: "file.jpg", mimeType: "image/jpg")
},
to: url).responseJSON
{ response in print(response)
if let status = response.response?.statusCode {
print(status)
}
//to get JSON return value
if let result = response.value {
let res = result as! [String: String]
let newUrl:String = res["url"]!
print(newUrl)
}
}

{
let id : String = UserDefaults.standard.string(forKey: "id")!
print(id)
self.view.makeToastActivity(.center)
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(UIImageJPEGRepresentation(self.imageView.image!, 0.5)!, withName: "profile_pic", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
for (key, value) in [“key”: "", ] {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
}, to:BaseURL + “base_url”)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
print("Upload Progress: \(Progress.fractionCompleted)")
})
upload.responseJSON { response in
if let JSON = response.result.value as? NSDictionary
{
print("JSON: \(JSON)")
let data = JSON["data"] as? NSArray
let status = JSON["status"] as? Int
if(status == 201)
{
}
}
self.view.hideToastActivity()
}
case .failure(let encodingError):
//self.delegate?.showFailAlert()
print(encodingError)
self.view.hideToastActivity()
}
}
}

Use Alamofire's upload method to upload your image in multipartFormData. i have updated the code for you. use below code.
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(expenseImage, withName: "file",fileName: "file.jpg", mimeType: "image/jpg")
},
with: baseUrl)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
print(response.result.value)
}
case .failure(let encodingError):
print(encodingError)
}
}

Related

Swift form-data using Alamofire 5 with parameters

I am beginner iOS developer and I don't know how to upload a file using Alamofire 5, I know there are a lot of similar questions, but all the topics here are from very old versions and I couldn't get it working. I tried this code, but I couldn't fit to my case, it gives me success, but file is not uploaded and the result I get is not what I get in postman. This is the code:
func uploadFile(_ parameters: Parameters) {
AF.upload(multipartFormData: { multipartFormData in
URLEncoding.default.queryParameters(parameters).forEach { (key, value) in
if let data = value.data(using: .utf8) {
multipartFormData.append(data, withName: key)
}
}
}, to: url)
.responseDecodable(of: FileCreation.self) { response in
switch response.result {
case .success(let data):
print(data, "success")
case .failure(let error):
print(error)
}
}
}
usage:
#IBAction func upload(_ sender: UIButton) {
guard let data = image?.jpegData(compressionQuality: 0.5)! else { return }
let parameters = ["addFiles": data]
uploadFile(parameters)
}
Here's Xcode output:
Here you can see postman response after I upload file:
Alamofire.upload(multipartFormData: {
multipartFormData in
if let imageData = image[0].jpegData(compressionQuality: 0.6) {
multipartFormData.append(imageData, withName: "addFiles", fileName: "file.pdf", mimeType: "application/pdf")
}
for (key, value) in param {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
},to: apiurl, method: .post, headers: headers, encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON {
response in
print(response.result)
}
//break
case .failure(let encodingError):
break
}
})
Try This
func uploadFilesToServer(_ url: String, method: HTTPMethod, parameters: [String:Any]?, file: [String:Any]?, fileType: String, fileName: String, headers:HTTPHeaders?, completionHandler: #escaping (_ result: Data?, _ success: Bool, _ status: String) -> ()) {
var status = Bool()
var message = String()
let url = URL(string: url)
AF.upload(multipartFormData: { multiPart in
if let files = file {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy-hh-mm-ss"
let dateString = dateFormatter.string(from: Date())
for (key, value) in files {
if fileType == "pdf" {
let filePath = URL(fileURLWithPath: value as! String)
multiPart.append(filePath, withName: "\(key)", fileName: fileName, mimeType: "file/pdf")
} else {
multiPart.append(value as! Data, withName: "\(key)", fileName: "Uploads\(dateString).png", mimeType: "image/png")
}
}
}
if let params = parameters {
for (key, value) in params {
multiPart.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}
}, to: url!, method: method, headers: headers ?? nil)
.validate()
.uploadProgress(closure: { progress in
print(progress)
})
.responseJSON { response in
switch response.result {
case .success(let responseData):
print(responseData)
case .failure(let networkErr):
switch networkErr {
case .responseSerializationFailed(reason: _):
message = "Something went wrong"
case .sessionTaskFailed(error: let err):
message = err.localizedDescription
default:
message = "Something went wrong"
}
completionHandler(nil, false, message)
break
}
}
}
usage
uploadFilesToServer(url, method: .post, parameters: params, file: uploadFile, fileType: "pdf", fileName: fileNme, headers: tokenHeader) { [self] responseData, isSuccess, responseMsg in
if isSuccess {
} else {
}
}

upload array of images with alamofire multipart

i upload array of images to server with alamofire multipart it uploades only first image (number of times array count) and doesnot upload the rest of images, i check every thing when get images from image picker to before and after appending image to multipart
extension profileViewController{
#objc private func UploadImage()
{
let headers = ["Authorization": "Bearer \(AuthService.instance.Auth_Token)"]
Alamofire.upload(multipartFormData: { multipartFormData in
if self.ImageArray?.isEmpty == false{
for (index, image) in self.ImageArray!.enumerated(){
print(index)
var imageData = image.jpegData(compressionQuality: 0.6)
print(imageData)
multipartFormData.append(imageData!, withName: "photos[]", fileName: "\(self.RandomString(length: 10)).jpeg",mimeType: "image/jpeg")
print(imageData)
imageData?.removeAll()
}
}else{
return
}
}, usingThreshold:UInt64.init(),
to: "http://couponsub.farid.azq1.com/api/save-user-photos"/*upload_imageUrl*/, //URL Here
method: .post,
headers: headers, //pass header dictionary here
encodingCompletion: { (result) in
switch result {
case .success(let upload, _, _):
print("the status code is :")
upload.uploadProgress(closure: { (progress) in
print(progress.fractionCompleted)
//self.ProgressBar.progress = CGFloat(Float(progress.fractionCompleted))
})
upload.responseJSON { response in
if response.result.isSuccess == true{
KRProgressHUD.dismiss()
}
print("the resopnse code is : \(String(describing: response.response?.statusCode))")
let json = try! JSON(data: response.data!)
print(json)
}
break
case .failure(let encodingError):
print("the error is : \(encodingError.localizedDescription)")
break
}
})
}
}
func uploadMultipleImages(imagesData:[Data]){
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)
}
})
}

Upload multiple image (Alamofire)

I have a little problem.
I would like to send several images to my server with Alamofire but I have an error.. the proxy tell me : "Invalid request"
My code here :
func uploadImage(TabImage: [UIImage]){
let urlReq = "http://www.myurl.com/upload.php"
let parameters = ["id": my_id]
Alamofire.upload(multipartFormData: { multipartFormData in
var i=0
for imageActuel in TabImage {
let tmp_image_data = UIImagePNGRepresentation(imageActuel)
let name = "exemple_"+ my_id +"_"+String(i)+"[]"
let filename = "exemple_"+ my_id +"_"+String(i)+".jpg"
multipartFormData.append(tmp_image_data!, withName: name,fileName: filename, mimeType: "image/jpg")
i+=1
}
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
},to:urlReq)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
print(response.result.value)
if let dic = response.result.value as? NSDictionary{
print(dic)
}
}
case .failure(let encodingError):
print(encodingError)
}
}
}
Do you see a problem in this function?
Thx for your help :)

Multipart Erro : Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength

I trying to make a upload using Alamofire, but return one erro : responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength), anyone knows what this ?
my code :
let image = #imageLiteral(resourceName: "img12345")
let imgData = UIImageJPEGRepresentation(image, 0.2)!
let parameters = ["Cookie": UsersService.get()?.kID]
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "fileset",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append((value?.data(using: String.Encoding.utf8)!)!, withName: key)
}
},to:"http://\(ServersService.getAtual()!.host)/hnzacerto/HnzAcertoViagemUploader")
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
print(response)
}
case .failure(let encodingError):
print(encodingError)
}
}
Thanks

Uploading Image to API Server using Alamofire

I have a question about Uploading Image to API server using Alamofire.
BaseURL: http://vietnamtravelguide-app.com/quangnam/api_inquangnam/tips/create?user_id=""&token=""
3 parameters : location_id, content, imageName
It's ok to post by POSTMAN
My Code:
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(image, withName: "imageName", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
}, with: path, encodingCompletion: {encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
print(response.result)
switch response.result {
case .success:
let json = JSON(response.result.value!)
if(delegate != nil) {
delegate!.didReceiveResult(json,basePath: basePath)
}
case .failure(let error):
print(error)
} }
case .failure(let encodingError):
print(encodingError)
}
})
with image ( image from parameter casting as Data). When I debug it , i got response.result return failure
You are not uploading the remaining two parameters content and location_id.
Try this one and see the result. I have also used SwiftyJSON here.
This is my APIManager class for all APIs handling.
import Alamofire
import SwiftyJSON
class APIManager: NSObject {
class func apiMultipart(serviceName:String,parameters: [String:Any]?, completionHandler: #escaping (JSON?, NSError?) -> ()) {
Alamofire.upload(multipartFormData: { (multipartFormData:MultipartFormData) in
for (key, value) in parameters! {
if key == "imageName" {
multipartFormData.append(
value as! Data,
withName: key,
fileName: "swift_file.jpg",
mimeType: "image/jpg"
)
} else {
//Data other than image
multipartFormData.append((value as! String).data(using: .utf8)!, withName: key)
}
}
}, usingThreshold: 1, to: serviceName, method: .post, headers: ["yourHeaderKey":"yourHeaderValue"]) { (encodingResult:SessionManager.MultipartFormDataEncodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
if response.result.error != nil {
completionHandler(nil,response.result.error as NSError?)
return
}
print(response.result.value!)
if let data = response.result.value {
let json = JSON(data)
completionHandler(json,nil)
}
}
break
case .failure(let encodingError):
print(encodingError)
completionHandler(nil,encodingError as NSError?)
break
}
}
}
}
If you don't have any header then you can leave the field as ["":""] in place of your ["yourHeaderKey":"yourHeaderValue"]
Now in order to call I just formed the parameters in the controller.
var params = [String:AnyObject]()
params["content"] = "something" as AnyObject?
params["location_id"] = "201" as AnyObject?
// Grab your image from some variable or imageView. Here self.profileImage is a UIImage object
if let profileImageData = self.profileImage {
if let imageData = UIImageJPEGRepresentation(profileImageData, 0.5) {
params["imageName"] = imageData as AnyObject?
APIManager.apiMultipart(serviceName: "http://yourAPIURL", parameters: params, completionHandler: { (response:JSON?, error:NSError?) in
//Handle response
})
} else {
print("Image problem")
}
}