I am trying to upload an image to the server using alamofire with basic authentication. I can send the image to the server, the image is in the server, but I can't get the JSON response from the server.
here is the code I use to send a defect image to the server
func uploadDefect(defectRemark: String, defectLocation: String, defectImage: UIImage, fileNameImage: String, completion: #escaping(_ errorMessage: String?) -> Void) {
guard let imgData = defectImage else {return}
let urlUpload = URLService.uploadDefect.endPoint
let username = "admin"
let password = "1234"
var headers: HTTPHeaders = [:]
if let authorizationHeader = Request.authorizationHeader(user: username, password: password) {
headers[authorizationHeader.key] = authorizationHeader.value
}
let parameters : [String:Any] = ["defect_remark" : defectRemark, "defect_location": defectLocation, "tenant_id" : tenantID]
let url = try! URLRequest(url: URL(string: urlUpload)!, method: .post, headers: headers)
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "file", fileName: fileNameImage, mimeType: "image/jpeg")
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
},
with: url,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
print("upload response: \(response)")
switch response.result {
case .failure(let error) :
let message : String
if let httpStatusCode = response.response?.statusCode {
print("httpStatusCode: \(httpStatusCode)")
switch(httpStatusCode) {
case 404:
message = "File not found"
case 500 :
message = "Internal Error"
default:
message = "Connection issue, please make sure you have a good internet access, or please contact IT Support."
}
} else {
message = error.localizedDescription
}
completion(message)
case .success( _) :
completion(nil)
}
}
case .failure(let encodingError):
let messageEncodingError = encodingError.localizedDescription
print(encodingError)
completion(messageEncodingError)
break
}
}
)
I try to debug the code, and it printed in my debugging area
upload response: FAILURE:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
1." UserInfo={NSDebugDescription=Invalid value around character 1.}))
httpStatusCode: 201
the httpStatusCode is 201, but I don't understand why it is failed response, as far as I know prefix 2xx is success, I really don't understand why response Serialization Failed. could you please help me to solve this problem?
Related
i try many solution but give always this error when upload image on server using alomafire
Trailing closure passed to parameter of type 'FileManager' that does not accept a closure
let params: Parameters = ["name": "abcd","gender": "Male", "hobbies" : HobbyArray]
AF.upload(multipartFormData:
{
(multipartFormData) in
multipartFormData.append(UIImageJPEGRepresentation(self.yourimageView.image!, 0.1)!, withName: "image", fileName: "file.jpeg", mimeType: "image/jpeg")
for (key, value) in params
{
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, to: "\(BaseUrl)/save-beers" , headers:nil)
{ (result) in
switch result {
case .success(let upload,_,_ ):
upload.uploadProgress(closure: { (progress) in
//Print progress
})
upload.responseJSON
{ response in
//print response.result
if response.result.value != nil
{
let dict :NSDictionary = response.result.value! as! NSDictionary
let status = dict.value(forKey: "status")as! String
if status=="1"
{
print("DATA UPLOAD SUCCESSFULLY")
}
}
}
case .failure(let encodingError):
break
}
}
You can use this code for uploading Image
//MARK: - Upload image using alamofire with multiparts
func uploadImageAPIResponse(postPath:String,img: UIImage, parameters:NSDictionary, requestType: RequestType){
let imgData = img.jpegData(compressionQuality: 0.5)!
let headers: HTTPHeaders = ["Authorization": "Your_Auth if any otherwise remove Header from request"]
print("postPath:\(postPath)\nheaders:\(headers)\nparameters: \(parameters)")
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "file",fileName: "profile.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key as! String)
} //Optional for extra parameters
},
to:postPath)
{ (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 as Any)
if response.result.isSuccess
{ let httpStatusCode: Int = (response.response?.statusCode)!
let data = (response.result.value as? NSDictionary)!
let meta = (data["meta"] as? NSDictionary)!
let code = meta["code"] as? Int ?? 0
print(data)
//if (data["success"] as? Bool)! {
print("httpCode" + String(httpStatusCode))
print("code" + String(code))
switch(httpStatusCode) {
case 200://operation successfull
if code == 401 {
let deleg = UIApplication.shared.delegate as! AppDelegate
User.defaultUser.logoutUser()
deleg.showLoginScreen()
}
self.delegate?.requestFinished(responseData: data, requestType: requestType)
break
case 204://no data/content found
self.delegate?.requestFinished(responseData: data, requestType: requestType)
break
case 401://Request from unauthorized resource
self.delegate?.requestFailed(error: "Request from unauthorized resource", requestType: requestType)
break
case 500://Internal server error like query execution failed or server script crashed due to some reason.
self.delegate?.requestFailed(error: "Internal server error like query execution failed or server script crashed due to some reason.", requestType: requestType)
break
default:
self.delegate?.requestFinished(responseData: data, requestType: requestType)
break
}
}
else
{
self.delegate?.requestFailed(error: (response.result.error?.localizedDescription)!, requestType: requestType)
}
}
case .failure(let encodingError):
print(encodingError)
self.delegate?.requestFailed(error: encodingError.localizedDescription, requestType: requestType)
}
}
}
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...
I am using alamofire 4.7 and swift 4
I need to upload image and json to server.
I am using the following code below for uploading bu I am getting result failure but data is inserting in server but not getting response, showing some serialization error as something like this
▿ result : FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
▿ failure : AFError
▿ responseSerializationFailed : ResponseSerializationFailureReason
▿ timeline : Timeline: { "Request Start Time": 548835779.066, "Initial Response Time": 548835779.074, "Request Completed Time": 548835779.127, "Serialization Completed Time": 548835779.127, "Latency": 0.008 secs, "Request Duration": 0.061 secs, "Serialization Duration": 0.000 secs, "Total Duration": 0.061 secs }
- requestStartTime : 548835779.06617701
- initialResponseTime : 548835779.07390201
- requestCompletedTime : 548835779.12704694
- serializationCompletedTime : 548835779.12748504
- latency : 0.0077250003814697266
- requestDuration : 0.060869932174682617
- serializationDuration : 0.00043809413909912109
- totalDuration : 0.061308026313781738
▿ _metrics : Optional<AnyObject>
=================================================================
let auth : String = MitraModal.sharedInstance().getBasicAuthenticationString()
let headers = ["Authorization": auth, "Content-type": "multipart/form-data"]
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append("\(parameters)".data(using: String.Encoding.utf8)!, withName: "data" as String)
if (!imageArray.isEmpty) {
for item in imageArray {
multipartFormData.append(item!, withName: "file", 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
if let JSON = response.result.value
{
print("JSON: \(JSON)")
onCompletion?(JSON as? JSON)
print("Successfully uploaded")
}
if let err = response.error {
onError?(err)
return
}
onCompletion?(nil)
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
onError?(error)
}
}
}
Anyone help ?
As i'm newbie, but Few days ago, i had same problem while uploading image, you must have to accept image by using file on the server side because of your image tag consist withName: "file" .
func AlamofireUploadImages(){
let url : String = URL_IP+"/ZameenServer/api/addNewProperty.php"
for img in HOUSEImages{
let data = UIImageJPEGRepresentation(img, 0.2)!
ImagesData.append(data)
}
let parameters = [
"userId" : "5",
"unit" : "6789"
] //Optional for extra parameter
Alamofire.upload(multipartFormData: { multipartFormData in
for imageData in self.ImagesData {
multipartFormData.append(imageData, withName: "file[]", fileName: self.randomString(length: 5)+".jpeg", mimeType: "image/jpeg")
}
for (key, value) in parameters {
multipartFormData.append((value?.data(using: String.Encoding.utf8)!)!, withName: key)
} //Optional for extra parameters
},
to:url)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON
{
response in
print("Response :\(response.result.value)")
}
case .failure(let encodingError):
print("no Error :\(encodingError)")
}
}
}
NOTE: As i'm uploading array of images so for uploading multile images use withName: "file[]" or for single image use withName: "file"
Might be it helps you.
Thanks
let url = BaseViewController.API_URL + "uploads"
let image = info[UIImagePickerControllerEditedImage] as? UIImage
let imgData = UIImageJPEGRepresentation(image!, 0.2)!
let parameters = [
"user_id" : UserDefaults.standard.value(forKey: "userId")!
]
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "uload_data",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
} //Optional for extra parameters
},
to:url)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
self.objHudHide()
print(response.result.value)
let jsonDict : NSDictionary = response.result.value as! NSDictionary
print(jsonDict)
if jsonDict["status"] as! String == "Success"
{
let detailDict : Dictionary = jsonDict["detail"] as! Dictionary<String,Any>
if let getTotalPrice = detailDict["total_price"]
{
self.lblTotalPrice.text = "$ \(getTotalPrice) + Free Shipping"
}
if let getTotalSize = detailDict["total_upload_size"]
{
self.lblTotalSize.text = "Total Size : \(getTotalSize)"
}
}
else
{
let alertViewController = UIAlertController(title: NSLocalizedString("Alert!", comment: ""), message:"Something Went wrong please try again." , preferredStyle: .alert)
let okAction = UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: .default) { (action) -> Void in
}
alertViewController.addAction(okAction)
self.present(alertViewController, animated: true, completion: nil)
}
}
case .failure(let encodingError):
print(encodingError)
}
}
I get the similar issue as well. This may cause several reasons. In my case that was the error of parameter key of the POST request. When you are executing following line
multipartFormData.append(item!, withName: "file", fileName: "image.png", mimeType: "image/png")
withName:"file" property refers the parameter key (key of the Json request) for the image of the POST request. So you can't use whatever the text you want here. Please add the correct parameter key of the image that your API is referring instead of "file". Let's say API access the image using "fileImage" as the parameter key. So the above line should be something like this.
multipartFormData.append(item!, withName: "fileImage", fileName: "image.png", mimeType: "image/png")
I am trying to upload an image using alamofire 4.7.1 with this code, but to be honest I suspect that I didn't write a right code to upload the image
func uploadDefect(defectRemark: String, defectLocation: String, defectImage: UIImage, fileNameImage: String, completion: #escaping(_ errorMessage: String?) -> Void) {
guard let imgData = defectImage.jpeg(.medium) else {return}
let urlUpload = URLService.uploadDefect.endPoint
let username = "admin"
let password = "1234"
let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8)!
let base64Credentials = credentialData.base64EncodedString(options: [])
let headers = ["Authorization": base64Credentials]
let parameters : [String:Any] = ["defect_remark" : defectRemark, "defect_location": defectLocation, "tenant_id" : tenantID]
let url = try! URLRequest(url: URL(string: urlUpload)!, method: .post, headers: headers)
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "file", fileName: fileNameImage, mimeType: "image/jpeg")
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
},
with: url,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
print("upload response: \(response)")
switch response.result {
case .failure(let error) :
let message : String
if let httpStatusCode = response.response?.statusCode {
switch(httpStatusCode) {
case 404:
message = "File not found"
case 500 :
message = "Internal Error"
default:
message = "Connection issue, please make sure you have a good internet access, or please contact IT Support."
}
} else {
message = error.localizedDescription
}
completion(message)
case .success( _) :
completion(nil)
}
}
case .failure(let encodingError):
let messageEncodingError = encodingError.localizedDescription
print(encodingError)
completion(messageEncodingError)
break
}
}
)
}
it seems that case .success is triggered
case .success( _) :
completion(nil)
}
but seems no error, but I didn't get the expected JSON response from the server.
here is the error log from the debugging area
I suspect that I didn't write a right code to upload the image server using alamofire using basic authentication. could you please help me with this one?
Change your Authorization like this:
let headers = ["Authorization": "Basic \(base64Credentials)"]
You can also make use of Alamofire to create the authentication header like:
var headers: HTTPHeaders = [:]
if let authorizationHeader = Request.authorizationHeader(user: user, password: password) {
headers[authorizationHeader.key] = authorizationHeader.value
}
I have to upload files on server using multipart request. For network calls i am using Alamofire.
What i have done so far is below
Request Service:
Multipart request:-
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
let fileData = Filedata() // getting data from local path
let URL = try! URLRequest(url: "https://SomeUrl/upload", method: .post, headers: headers)
Alamofire.upload(multipartFormData: { (multipartFormData) in
//multipartFormData.append(fileData, withName: "image", fileName: "image", mimeType: "image/png")
multipartFormData.append(fileData, withName: "file")
}, with: URL, encodingCompletion: { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
print(response)
}
case .failure(let encodingError):
print(encodingError)
}
})
Response:-
{ Status Code: 400, Headers {
Connection = (
close
);
"Content-Type" = (
"application/json;charset=UTF-8"
);
Date = (
"Tue, 15 May 2018 10:34:15 GMT"
);
"Transfer-Encoding" = (
Identity
);
} }
[Data]: 171 bytes
[Result]: SUCCESS: {
error = "Bad Request";
message = "Required request part 'file' is not present";
path = "/files/safebolt.org/upload";
status = 400;
timestamp = "2018-05-15T10:34:15.715+0000";
}
Can anyone please tell me what i am doing wrong with request ?
Try with:
multipartFormData.append(fileData, withName: "file", fileName: "file", mimeType: "image/png")
I have created one function. Hope it works for you.
//Alamofire file upload code
func requestWith(URLString: String,
imageData: Data?,
fileName: String?,
pathExtension: String?,
parameters: [String : Any],
onView: UIView?,
vc: UIViewController,
completion:#escaping (Any?) -> Void,
failure: #escaping (Error?) -> Void) {
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
let URL = BASE_PATH + URLString
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: "fileUpload", fileName: "\(fileName!).\(pathExtension!)", mimeType: "\(fileName!)/\(pathExtension!)")
}
}, usingThreshold: UInt64.init(), to: URL, method: .post, headers: headers) { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
if let err = response.error {
failure(err)
return
}
completion(response.result.value)
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
failure(error)
}
}
}
Try This, is an example it works for me. If you want to convert encode 64 for images add extension. If simply post the data and image this code may help.
//creating parameters for the post request
let parameters: Parameters=[
"ad_title":classText1.text!,
"ad_description":classText2.text!,
"ad_category":CategoryClass.text!,
"ad_condition":classText3.text!,
"ad_username":classText6.text!,
"ad_usermobile":classText7.text!,
"ad_city":classText8.text!,
"ad_price":classText4.text!,
"negotiable":classText5.text!,
"image1":adImage1.image!,
"image2":adImage2.image!,
"image3":adImage3.image!,
"image4":adImage4.image!
]
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}, usingThreshold: UInt64.init(), to: URL, method: .post) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded = \(response)")
if let err = response.error{
print(err)
return
}
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
}
}