I seem to have a problem regarding image upload and passing parameters using Alamofire. I have a quite simple function for multipart data which looks like:
sessionManager.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
print("\(value)")
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
multipartFormData.append(UIImagePNGRepresentation(image)!, withName: "document", mimeType: "image/png")
}, to: baseURL + "/documents", encodingCompletion: { (result) in
switch result{
case .success(let upload, _, _):
upload.validate().responseJSON { response in
print("Succesfully uploaded")
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
}
})
I have OAuth2Handler which i've implemented for headers and authorisation and it works for all other requests. I have also tried to implement this without wrapper using Alamofire object directly but still no luck. When I inspect the request i notice that httpBody is always nil, which corresponds to error I get from the server and the message says that I do not pass required parameters.
This is Working for me Swift 4
func callPostApiImage(api:String, parameters:[String:AnyObject]?,image:UIImage,Name:String, mime_type:String = "image/jpg", complition:#escaping (AnyObject)->Void){
// Encode Data
let base64EncodedString = toBase64EncodedString(toJsonString(parameters: parameters!))
let File_name = "image_" + String(arc4random()) + ".jpg"
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(UIImageJPEGRepresentation(image, 0.5)!, withName: Name, fileName: File_name, mimeType: mime_type)
multipartFormData.append(base64EncodedString.data(using: String.Encoding.utf8)!, withName: "jsondata")
}, to:api){ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print(progress)
})
upload.responseJSON { response in
print(response.result)
}
case .failure(let encodingError):
print("",encodingError.localizedDescription)
break
}
}
}
// Base64EncodedString
func toBase64EncodedString(_ jsonString : String) -> String
{
let utf8str = jsonString.data(using: .utf8)
let base64Encoded = utf8str?.base64EncodedString(options: [])
return base64Encoded!
}
Related
I am trying to upload multiple images and parameters to the server using 'Alamofire 5.2)'
This is what the server expects
[{"key":"media1","description":"","type":"file","value":["/C:/Users/x/x/x/x.jpg"]},
[{"key":"media2","description":"","type":"file","value":["/C:/Users/x/x/x/x.jpg"]},
[{"key":"media3","description":"","type":"file","value":["/C:/Users/x/x/x/x.jpg"]},
{"key":"model","value":"{\"emp_Id\": \"6\",\"device_Identifier\":\"Device 01\",\"timestamp\":\"123\,”\description\”:\”description\",”handoverStatus”:”false”}","type":"text"}]
//Please note the array part
This is how i add picked image to an image array
var dictImage : [UIImage]?
if pickedImage.pngData() != nil
{
dictImage!.append(pickedImage)
}
This is how im trying to call the alamofire upload
func xyz()
{
let param : [String: Any] = [
"emp_Id" : "",
"device_Identifier" : "",
"timestamp" : "",
"description" : "",
"handoverStatus" : ""
]
let urlString = URL(string: APIDetails.BaseUrl + "api/123")!
let url = (try? URLRequest(url: urlString, method: .post, headers: APIDetails.header))!
AF.upload(multipartFormData: { (multipartData) in
let img1 = arrImage![0]
let img2 = arrImage![1]
let img3 = arrImage![2]
multipartData.append(img1.pngData(), withName:"media1", fileName: "\(Date().timeIntervalSince1970).jpg", mimeType: "file")
multipartData.append(img2.pngData(), withName:"media2", fileName: "\(Date().timeIntervalSince1970).jpg", mimeType: "file")
multipartData.append(img3.pngData(), withName:"media3", fileName: "\(Date().timeIntervalSince1970).jpg", mimeType: "file")
for (key, value) in param {
multipartData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, with: url)
}
How do i upload every image and its details as a dictionary?
How do i add upload progress and result that shows if anything failed or not ?
I tried with
}, with: url,encodingCompletion:{
EncodingResult in
switch EncodingResult{
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint("SUCCESS RESPONSE: \(response)")
}
case .failure(let encodingError):
print("ERROR RESPONSE: \(encodingError)")
} })
But it gives error Extra argument 'encodingCompletion' in call
(This is my first time trying to upload multipart form data, the code/part of it was taken from another answer)
try this code, I have not tested in Alamofire(5.2)
let baseUrl = "your URL"
let fullUrl = baseUrl + strUrl
var headers : HTTPHeaders = HTTPHeaders(["Content-type" : "multipart/form-data"])
if let header = header{
headers = header
}
guard let url = try? URLRequest(url: fullUrl, method: .post, headers: headers) else {return}
AF.upload(multipartFormData: { (multipartData) in
for i in 0 ..< arrImage.count{
if let imageData = arrImage[i].pngData(){
let mediaName = "media\(i + 1)"
multipartData.append(imageData, withName:mediaName, fileName: "\(Date().timeIntervalSince1970).jpg", mimeType: "file")
}
}
for (key, value) in parameter {
multipartData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, to: url).responseJSON(queue: .main, options: .allowFragments) { (response) in
switch response.result{
case .success(let value):
print("Json: \(value)")
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}.uploadProgress { (progress) in
print("Progress: \(progress.fractionCompleted)")
}
After migrating to 5.0 receive this error - > Module 'Alamofire' has no member named 'upload'
Changing Alamofire to AF doesn't help.
Can't run build in xcode due to this error.
Alamofire.upload(
multipartFormData: { (multipartFormData) in
formData.forEach({ (key, value) in
guard let valueData = "\(value)".data(using: .utf8) else {
return
}
multipartFormData.append(valueData, withName: key)
})
switch uploadOption {
case .data(let data, let meta):
multipartFormData.append(
data,
withName: "file",
fileName: meta.fileName,
mimeType: meta.mimeType
)
case .stream(let stream, let length, let meta):
multipartFormData.append(
stream,
withLength: length,
name: "file",
fileName: meta.fileName,
mimeType: meta.mimeType
)
}
},
to: url,
encodingCompletion: { (encodingResult) in
switch encodingResult {
case .failure(let error):
completion(.failure(error: error))
case .success(let request, _, _):
cancelable.request = request
request.responseData(completionHandler: { (response) in
if let error = response.error {
completion(.failure(error: error))
return
}
completion(.success)
})
}
})
I have Alamofire version 5.2, it seems ok,
some syntax changed after you migrate to 5.x,
plz check it or update it to 5.2
I have upgraded the pod Alamofire 5.0 from an older version,
From the Migrating Guide
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%205.0%20Migration%20Guide.md
"MultipartFormData’s API has changed and the top level upload methods to create and upload MultipartFormData have been updated to match other request APIs, so it’s not longer necessary to deal with the Result of the multipart encoding."
I have the below function written, i am unable to re-write this in the new version, Can anyone help me on this regard?
note:
I think i need to change the "Alamofire.upload" -> "AF.upload", however its not along is enough to fix the problem,
func uploadPhoto(token:String, userID: String, data: Data, dataUrl: URL) -> Observable<AnyObject?> {
return Observable<AnyObject?>.create({ (observer) -> Disposable in
print(userID);
print(data);
do {
let urlRequest = try URLRequest(url: ResourcePath.Upload.path + "/\(userID)" , method: .post)
Alamofire.upload(multipartFormData: { (multipartData) in
multipartData.append(data, withName: "Filedata", fileName: dataUrl.absoluteURL.lastPathComponent, mimeType: "image/jpeg")
//append(dataUrl, withName: "Filedata", fileName: dataUrl.absoluteString, mimeType: "image/png")
}, with: urlRequest, encodingCompletion: { (result) in
switch result {
case .success(let value, let t1, let t2) :
print(value)
value.responseData(completionHandler: { (dataResponse) in
switch (dataResponse.result) {
case .success(let value) :
print(value)
do {
let jsonData = JSON(dictData)
print("Upload photo response: \(jsonData)")
observer.onNext(jsonData as AnyObject?)
observer.onCompleted()
}
catch {
print(error)
observer.onError(error)
return
}
break
case .failure(let error) :
print(error)
observer.onError(error)
break
}
})
break
case .failure(let error) :
print(error)
observer.onError(error)
break
default:
break
}
})
} catch {
print(error)
observer.onError(error)
}
return Disposables.create {
print("disposed")
}
})
}
Alamofire 5 has removed the need for the encodingCompletion closure when using multipart form encoding. Instead, you can use the normal response handling as seen in other use cases. For example:
AF.upload(multipartFormData: { data in
// Build your multipart form.
}).responseDecodable(of: SomeType.self) { response in
// Handle response.
}
i am trying to send an image to an api using alamofire heres what i got:
var uploadedProfileImage: UIImage = UIImage()
let body: Parameters = [
"profilePic": uploadedProfileImage,
"name": "John Doe"
]
Alamofire.request(BASE_URL",method: .post,parameters: body,encoding: JSONEncoding.default).responseData { response in
debugPrint("All Response Info: \(response)")
if let data = response.result.value, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
}
}
so this is the code i am using uploadProfileImage has an image that the user picked from the library and my api receives a json body parameter in which it has profilePic which is off type file when i run this its giving me an error saying 'Invalid type in JSON write (UIImage)'.theres is also a terminating with uncaught exception of type NSException error. what am i doing wrong and how to fix it?
You can't upload image with
"profilePic": uploadedProfileImage
as it's used for types that are encode-able such as strings , you need
upload image to server using Alamofire
func uploadImageAndData(_ url:String,parameters1:Parameters,headers1:HTTPHeaders,images:[UIImage]){
Alamofire.upload(multipartFormData: { multipartFormData in
// import image to request
var i=0
for imageData in images {
// multipartFormData.append(self.resizeImage(image: imageData, targetSize: CGSize(width: 400, height:
multipartFormData.append(imageData.pngData()!, withName: "image", fileName: "image"+".jpeg", mimeType: "image/jpeg")
i += 1
}
for (key, value) in parameters1 {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
} ,to: url,method:.post,
headers:[:],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
print("Upload Progress: \(Progress.fractionCompleted)")
//SwiftSpinner.show(progress: Progress.fractionCompleted*100, title: "تحميل")
})
upload.responseJSON { response in
switch response.response?.statusCode {
case 200 :
break
case 400 :
break
case 401 :
break
case 302 :
break
case 500 :
break
default: break
}
}
return
case .failure(let encodingError):
}
})
}
var head = [String:Any]()
head["Accept"]="application/json"
head["Authorization"] = "Bearer \(tokenIfExists)"
I'm trying to upload an array of images to the server using Alamofire 4.8.2
Here is the function:
func uploadMultiplePhotos(centreId: Int, imagesArray: [UIImage]) {
let parameters = ["ec_id": centreId, "uploaded_image": imagesArray] as [String : Any]
Alamofire.upload(multipartFormData: { (multipartFormData : MultipartFormData) in
let count = imagesArray.count
for i in 0..<count{
multipartFormData.append(imagesArray[i], withName: "photo[\(i)]", fileName: "photo\(i).jpeg", mimeType: "image/jpeg")
}
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
print(multipartFormData)
}, to: storeCentreImageURL) { (result) in
switch result {
case .success(let upload, _ , _):
upload.uploadProgress(closure: { (progress) in
print("uploding: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
print(response.result.value!)
}
case .failure(let encodingError):
print("failed")
print(encodingError)
}
}
}
getting error in the line below:
multipartFormData.append(imagesArray[i], withName: "photo[\(i)]", fileName: "photo\(i).jpeg", mimeType: "image/jpeg")
Cannot invoke 'append' with an argument list of type '(UIImage, withName: String, fileName: String, mimeType: String)'
You need to convert the image to data
imagesArray.indices.forEach {
multipartFormData.append(imagesArray[$0].jpegData(compressionQuality:0.8)!, withName: "photo[\($0)]", fileName: "photo\($0).jpeg", mimeType: "image/jpeg")
}