Swift: Alamofire: e_invalid_json - ios

I'm working on a company project who use Alamofire to connect to a Dittofi API.
I'm getting a 0 status code and a weirdly null output. Heres the code (I can only release this as per my NDA):
self.manager.upload(multipartFormData: {
multipartFormData in
for (key, value) in params{
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}
}, to: createAssignmentURL, encodingCompletion: {
(result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON {
response in
switch response.result {
case .success(let j):
let json = JSON(j)
print("JSON: ", json)
let message = json["statusMessage"].stringValue
let status = json["statusCode"].intValue
let data = json["data"]
if status == 200{
completion(message,"",status)
}else{
let errorMessage = data["error_msgs"].stringValue
self.reportError(message: errorMessage)
completion(errorMessage,"",status)
}
case .failure(let error):
if error._code == NSURLErrorTimedOut {
completion(App.CONNECTION_TIMEOUT,"",App.STATUS_TIMEOUT)
}
else if error._code == NSFileNoSuchFileError {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
else {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
}
}
case .failure(let error):
if error._code == NSURLErrorTimedOut {
completion(App.CONNECTION_TIMEOUT,"",App.STATUS_TIMEOUT)
}
else if error._code == NSFileNoSuchFileError {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
else {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
}
})
Heres the output:
JSON: {
"data" : null,
"error" : {
"message" : "",
"param" : "",
"code" : "e_invalid_json"
}
}
I'm certain something is wrong with the way I post but I cant seem to figure it out. I also get a 0 status code which apparently means that the response is empty. Is this a problem with my code or the API?

Related

Issue with AF.upload "Pattern cannot match values of type URLRequest”

I am not able to debug this error in handling response of multipartFormData of AF.upload.
The error 'Pattern cannot match values of type "URLRequest" shows up on the 2 case statements success and failure.
I tried using the two methods described in this Stackoverflow post and .responseDecodables suggested in another post. There is not much reference material out there for this error as it relates to AF.upload. Help!
AF.upload(multipartFormData: { (multipartFormData) in
if let param = parameter{
for (key, value) in param {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key)
}
}
}, to:url, usingThreshold:UInt64.init(), method:.post)
{ result in
switch result {
case .success(let upload, , ):
upload.uploadProgress(closure: { (progress) in
})
upload.responseJSON { response in
Indicator.shared().stop()
//print(response)
if let data = response.value as? NSArray{
// //print(data)
completion(data,(response.response?.statusCode)!)
}
else{
completion(nil,(response.response?.statusCode) ?? 0)
}
}
case .failure(let encodingError):
Indicator.shared().stop()
// //print(encodingError.localizedDescription)
completion(nil,0)
break
}
}
}
You need to update your implementation for Alamofire 5 by removing the result switch and moving your response methods to the end of the chain.

How to convert UIImage to JPEG without loosing exif data?

I'm currently working on iOS applications and I'm using multipart image upload to uploading images to the server. Following is my image uploading method.
func uploadImageData(imageType:Int, uploadId:String, fileName:String, imageFile:UIImage, completion:#escaping (APIResponseStatus, ImageUploadResponse?) -> Void) {
let image = imageFile
let imgData = image.jpegData(compressionQuality: 0.2)!
let params = [APIRequestKeys.imageType:imageType, APIRequestKeys.uploadId:uploadId, APIRequestKeys.fileName:fileName] as [String : Any]
//withName is the post request key for the image file
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imgData, withName: APIRequestKeys.imageFile, fileName: "\(fileName).jpg", mimeType: "image/jpg")
for (key, value) in params {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key)
}
}, to: Constants.baseUrl + APIRequestMetod.uploadImageData, headers:self.getImageUploadHeaders())
{ (result) in
switch result {
case .success(let upload, _, _):
APIClient.currentRequest = upload
upload.uploadProgress(closure: { (progress) in
})
upload.responseObject {
(response:DataResponse<ImageUploadResponse>) in
switch response.result {
case .success(_):
completion(APIClient.APIResponseStatus(rawValue: (response.response?.statusCode)!)!, response.value!)
case .failure(let encodingError):
if let err = encodingError as? URLError, err.code == .notConnectedToInternet {
completion(APIClient.APIResponseStatus.NoNetwork, nil)
} else {
completion(APIClient.APIResponseStatus.Other, nil)
}
}
}
case .failure( _):
completion(APIClient.APIResponseStatus.Other, nil)
}
}
}
But for this implementation server is always sending exif data error. Following is the error that I'm getting.
exif_read_data(A029C715-99E4-44BE-8691-AA4009C1F5BD_FOTOPREGUNTA.ico): Illegal IFD size in
upload_image_xhr.php on line
The important thing is this service is working without errors in POSTMAN and android application as well. This error is only getting for my iOS implementation. My backend developer telling me that there is and exif data error in data that I'm sending and please verify the data from my side.
Anyone have an idea about this?
Thanks in advance.
I will make block function for Upload image 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,valus) in imageDic
{
MultipartFormData.append(valus, 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,[:]);
}
}
}
I Hope this will help...

Upload multipart image with parameters in IOS

I am new to IOS n want to upload the image with parameters to server but it's not uploading. I tried a lot refer the alamofire and also base64 but nothing is working for me. Did I miss any thing, any help to understand this?
Thanks in advance. Please help me to resolve issue
Below is my code:
#IBAction func submitBtnClicked(_ sender: Any)
{
//parameters
var number: Int?
number = 47000482
var srNumber = String(format:"%d",number!)
var urlString: String = filePath!.absoluteString
var parameters = ["s_no":srNumber, "count":"1"]
let imgData = UIImageJPEGRepresentation(self.chosenImage!, 0.5)
print(parameters)
print(imgData)
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imgData!, withName:"filestream", fileName:(self.filePath?.lastPathComponent)!, mimeType: "image/jpeg")
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName:key)
}
}, to:"https://********************")
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
print("Upload Progress: \(Progress.fractionCompleted)")
})
upload.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
case .failure(let encodingError):
//self.delegate?.showFailAlert()
print(encodingError)
}
}
}
//MARK: - Multiple Images Uploading API Call
func serviceUploadMultipleImageData(model : UploadImageResponseModel,isLoader:Bool = true,name:String = "", loaderViewcontoller : UIViewController? = nil,url: String, method: HTTPMethod, InputParameter: Parameters?, ServiceCallBack: #escaping (_ Completion: ServiceResponseNormal, _ isSuccess:Bool)-> Void) {
let viewContoller = loaderViewcontoller
guard Reachability.isConnectedToNetwork() else {
Singleton.sharedSingleton.showPopup(title: "No Internet", message: HttpCode.NoInternetConnection.message(), image: nil, VC: viewContoller!)
ServiceCallBack(self.setCustomResponse(Code: HttpCode.NoInternetConnection.rawValue, Message: "No Internet Connection"),false)
return
}
if isLoader == true {
if viewContoller != nil {
ProgressHUD.startLoading(onView: (viewContoller?.view)!)
} else {
ProgressHUD.startLoading(onView: appDelegate.window!)
}
}
Alamofire.upload(multipartFormData: { (multipartFormData) in
for obj in model.arrImages{
multipartFormData.append(obj.imageData!, withName:obj.imgName, fileName: "", mimeType: "image/jpg")
}
for (key, value) in InputParameter! {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue, allowLossyConversion: true)!, withName: key)
}
}, to:url)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
model.progress = Progress.fractionCompleted
})
upload.responseJSON { response in
if isLoader == true {
if viewContoller != nil {
ProgressHUD.stopLoading(fromView: (viewContoller?.view)!)
}else {
ProgressHUD.stopLoading(fromView: appDelegate.window!)
}
}
if(response.result.isSuccess){
print(response)
do{
if response.data != nil{
var responseParsed = try JSONDecoder().decode(ServiceResponseNormal.self, from: response.data!)
if responseParsed.Code == "200"
{
responseParsed.Data = response.data
ServiceCallBack(responseParsed, true)
}
else
{
Singleton.sharedSingleton.showPopup(title: "Error", message: responseParsed.Message ?? "Error", image: nil, VC: viewContoller!)
ServiceCallBack(responseParsed, false)
}
}
}
catch let error {
print(error.localizedDescription)
var falilure = ServiceResponseNormal()
falilure.Data = nil
falilure.Message = "Response could not parsed"
ServiceCallBack(falilure, false)
}
}
else{
if let error = response.result.error{
let message = error.localizedDescription
var falilure = ServiceResponseNormal()
falilure.Data = nil
falilure.Message = message
ServiceCallBack(falilure, false)
Singleton.sharedSingleton.showPopup(title: "Error", message: message, image: nil, VC: viewContoller!)
}
}
}
case .failure(let encodingError):
let message = encodingError.localizedDescription
var falilure = ServiceResponseNormal()
falilure.Data = nil
falilure.Message = message
ServiceCallBack(falilure, false)
Singleton.sharedSingleton.showPopup(title: "Error", message: message, image: nil, VC: viewContoller!)
}
}
}
Firstly you need to add method type i.e .post or .put type with along with url then you will able to send the image data and also increase the timeout interval for request of session manager.session.configuration.timeoutIntervalForRequest = 120 If you have any query you reply me on same So I will try to resolve your problem.
class func requestForAPI(param:Dictionary<String, String>?, Url:String,image:UIImage,isShowLoader:Bool, headers:[String:String]?, completion: #escaping (_ result: AnyObject?, _ error: Error?) -> Void) {
let reach:Reachability = Reachability.forInternetConnection()
let netStatus:NetworkStatus = reach.currentReachabilityStatus()
if (netStatus == NotReachable)
{
NSUtility.shared().showMessage(title: "Alert!", body: "Please connect to the internet to continue", themetype: .error)
return
}
if isShowLoader == true{
APPDELEGATE?.showLoaderView()
}
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 120
let imageData = image.jpegData(compressionQuality: 0.8)
manager.upload(multipartFormData:
{
(multipartFormData) in
multipartFormData.append(imageData, withName: "file", fileName: "file.jpeg", mimeType: "image/jpeg") for (key, value) in param {
multipartFormData.append(value.data(using:String.Encoding.utf8.rawValue)!, withName: key)
}, to:URL(string: Url)!,method:.put, headers:headers)
{ (result) in
switch result {
case .success(let upload,_,_ ):
upload.uploadProgress(closure: { (progress) in
//Print progress
})
upload.responseJSON
{ response in
APPDELEGATE?.dismissLoader()
//print response.result
if response.result.value != nil
{
print (response.result.value as Any)
completion(response.result.value as AnyObject? , nil)
}
}
case .failure(let encodingError):
print(encodingError)
completion(nil, encodingError)
break
}
}}}

Upload image to AWS S3 using alamofire upload

I am trying to upload jpeg image to AWS using upload function. But i am getting the following error :
nw_endpoint_handler_add_write_request [29.1 52.92.250.6:443 failed socket-flow (satisfied)] cannot accept write requests
Some help would be of great use. Here is the code i am using (params is of type Data)
let request = Alamofire.upload(params, to: url, method: .put, headers: ["Content-Type":"image/jpeg"])
request.responseJSON { (responseJson) in
switch responseJson.result {
case .success:
print("Success: \(responseJson.result.value)")
break
case .failure:
print("Call failed: \(responseJson.result.value)")
break
default:
print("____")
}
}
Probably best to use Amazon's own SDK for doing this.
http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html
Try with this:
Swift 3.x:
func uploadImageWith(parameter params:Dictionary<String,String>,image:UIImage?,handler:#escaping ((Dictionary<String,Any>?) -> Void)) {
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in params {
multipartFormData.append(value.data(using: String.Encoding.utf8, allowLossyConversion: false)!, withName: key)
}
if image != nil {
if let imgData = UIImageJPEGRepresentation(image!, 0.5) {
multipartFormData.append(imgData, withName: "photo_upload", fileName: "file.png", mimeType: "image/png")
}
}
}, to: "http://") { (encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
switch response.result {
case .success:
if let jsonDict = response.result.value as? Dictionary<String,Any> {
print("Json Response: \(jsonDict)")
handler(jsonDict)
print(jsonDict,(response.response!.statusCode))
}
else{
print(response.response!.statusCode)
handler(nil)
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Server Response: \(utf8Text)") // original server data as UTF8 string
}
break
case .failure(let error):
print(response.response!.statusCode)
print_debug(error)
handler(nil)
break
}
}
case .failure(let encodingError):
print(encodingError)
}
}
}
Usage:
uploadImageWith(parameter: ["key":"value"], image: UIImage(named:"demo")) { (response) in
if response != nil {
print(response)
} else {
print("Something went wrong")
}
}

Error Handling with Alamofire in Swift 2

Hi I am practising some code, my code is fine with case .Success(let value): and it is displaying alert but will case .Failure(let error): display alert with The 4xx class of status code?
Alamofire.request(.GET, URL).responseJSON { (response) -> Void in
if let value = response.result.value {
let json = JSON(value)
switch response.result {
case .Success(let value):
let name = json["name"].string
if let nothing = name {
self.alertMessage(message: "Name not Found")
} else {
self.alertMessage(message: "Name Found")
}
case .Failure(let error):
self.alertMessage(message: "Error 4xx / 5xx")
}
You can use validate to check status codes:
Alamofire.request(.GET, URL)
.validate() // or, if you just want to check status codes, validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .Success(let value):
let json = JSON(value)
if let name = json["name"].string {
self.alertMessage(message: "Name Found: \(name)")
} else {
self.alertMessage(message: "Name not Found")
}
case .Failure(let error):
self.alertMessage(message: "Error 4xx / 5xx: \(error)")
}
}
Or, in Swift 3:
Alamofire.request(url)
.validate() // or, if you just want to check status codes, validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
if let name = json["name"].string {
self.alertMessage(message: "Name Found: \(name)")
} else {
self.alertMessage(message: "Name not Found")
}
case .failure(let error):
self.alertMessage(message: "Error 4xx / 5xx: \(error)")
}
}
Also note that you should probably move the examination of response.result.value to inside the Success section (or just grab the value passed there). Also, the determination of whether name is found was backwards.

Resources