Swift AlamoFire PUT request - swift

I have a JSON file with this struct:
{
"example": {
"projects": [
{ "projectname" : "abc",
"date" : "20200930",}
{ "projectname" : "bac",
"date" : "20200803",}
]
}
}
I want to update first projectname, but not the date connected to it. But the AF.request method give me back error 400 (Invalid JSON body passed.)
let user = "username"
let password = "password"
let params = ["example":
["projects":
["projectname": "New Name"]
]
]
let credentialData = "\(user):\(password)".data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
let base64Credentials = credentialData.base64EncodedString()
let headers : HTTPHeaders = [
"Authorization": "Basic \(base64Credentials)",
"Accept": "application/json",
"Content-Type": "application/json" ]
AF.request("https://example.com/api", method: .put, parameters: params, headers: headers).responseJSON { AFdata in
do {
guard let jsonObject = try JSONSerialization.jsonObject(with: AFdata.data!) as? [String: Any] else {
print("Error: Cannot convert data to JSON object")
return
}
guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) else {
print("Error: Cannot convert JSON object to Pretty JSON data")
return
}
guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8) else {
print("Error: Could print JSON in String")
return
}
print(prettyPrintedJson)
} catch {
print("Error: Trying to convert JSON data to string")
return
}
}
Thanks for your help!

I believe you are missing the encoder parameter in you request:
AF.request("https://example.com/api", method: .put, parameters: params, headers: headers, encoder: JSONParameterEncoder.default).responseJSON { AFdata in
Without it Alamofire cannot know that your parameters should be encoded as JSON.

Related

How to send an array of json as value for multipart/form-data content type?

Guys I need to send parameters described in the image value where content type is multipart/form-data. Im having difficulty in sending only package_json parameter.
The problem is I don't know how do I send multiple package_json values as parameter? I can send one value like this:
let param = [
"outletId : "1",
"vehicleId" : "1",
"instructions" : tvInstructions.text,
"package_json" : "[{\"packageId\":\"1\"}]",
"addressId" : "1"
]
Above i'm able to send package_json = [{"packageId": 1}] as String as my function below sends parameters as [String : String] and images of Data type as [String : Any]. Im having problem sending multiple values in package_json. For eg. something like this: [{"packageId": 1}, {"packageId": 2}, {"packageId": 3}] and so on. Here's the function that i'm using to send parameters:
func postrequest(_ request: String, onPath imagesData:[Data]?,_ imageName : String, andParameter parameters: [String:String]?, withCompletion response: #escaping serviceCompletion) {
let headers: HTTPHeaders
headers = ["Content-type": "multipart/form-data"]
AF.upload(multipartFormData: { multiPart in
if let allParams = parameters {
for (key, value) in allParams {
multiPart.append(value.data(using: .utf8)!, withName: key)
}
}
for imageData in imagesData ?? [] {
multiPart.append(imageData, withName: "\(imageName)", fileName: "file.jpg", mimeType: "image/jpg")
}
}, to: request, usingThreshold: UInt64.init(),
method: .post,
headers: headers).response { (res) in
if((res.error == nil)){
do {
response(res.data,res.error)
}
}
else{
// hideHud()
response(res.data,res.error)
}
}
}
I tried to convert function to send [String: Any] data but found out we can only send as [String : String] along with images as [String : Any].
I just want to know if there is any way to modify "package_json" : "[{\"packageId\":\"1\"}]" so I can send [{"packageId": 1}, {"packageId": 2}, {"packageId": 3}]?
Just in case, this is how im calling above function and sending parameters:
func sendData() {
let param = [
"outletId" : "1",
"vehicleId" : "1",
"instructions" : tvInstructions.text,
"package_json" : "[{\"packageId\":\"1\"}]",
"addressId" : "1"
]
ApiNetworkManager.shared.postrequest(Api.completeUrl, onPath: [], "", andParameter: param) { (response, err) in
ApiNetworkManager.shared.hideHud()
debugPrint(param)
let json = JSON.init(response!)
debugPrint(json)
if err == nil {
if err == nil && response != nil {
if json.dictionaryValue["success"]?.stringValue == "1" {
//Add your code here
}
else{
let message = json.dictionaryValue["message"]?.stringValue
self.showAlert(Message: message ?? "Error")
}
} else {
// hideHud()
print(err?.localizedDescription as Any)
let message = json.dictionaryValue["message"]?.stringValue
self.showAlert(Message: message ?? "Error")
}
}
else{
ApiNetworkManager.shared.hideHud()
let message = err?.localizedDescription
self.showAlert(Message: message ?? "Error")
}
}
}

Uploading multiple images(with parameters) using multipart form data - Alamofire 5

I have been trying to upload multiple images(3) with parameters using alamofire but i cant seem to do it.(My lack of knowledge). Could someone kindly help me out with this?
This is what i have tried
{
let headers: HTTPHeaders = [
xyz
]
let param : [String: Any] = [
"emp_Id" : "",
"device_Identifier" : "",
"timestamp" : "",
"description" : "",
"handoverStatus" : ""
]
AF.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(imgData0, withName: "media1" , fileName: "file0.jpeg", mimeType: "image/jpeg")
multipartFormData.append(imgData1, withName: "media2",fileName: "file1.jpg", mimeType: "image/jpg")
multipartFormData.append(imgData2, withName: "media3",fileName: "file1.jpg", mimeType: "image/jpg")
// I think im supposed to add the last part here but i dunno how to do that
},
to: "http://ip.here.--.--/new.php", method: .post , headers: headers)
.response { resp in
print(resp)
}
}
This is what the server expects
[{"key":"media1","description":"","type":"file","value":["/C:/Users/x/x/Saved Pictures/x.jpg"]},
[{"key":"media2","description":"","type":"file","value":["/C:/Users/x/x/Saved Pictures/x.jpg"]},
[{"key":"media3","description":"","type":"file","value":["/C:/Users/x/x/x.jpg"]},
{"key":"model","value":"{\"emp_Id\": \"6\",\"device_Identifier\":\"Device 01\",\"timestamp\":\"\123\,
”\description\”:\”description\",”handoverStatus”:”false”}","type":"text"}]
I dunno how to add the last part to the multipart form data, could some point me in the right direction ?
Thanks
Try this method to upload multiple images
class func uploadImageWithURL(endPath : String, dictImage : [String:[UIImage]], parameter : [String : Any], header : HTTPHeaders? = nil, success : #escaping ( Any? )->Void, failure : #escaping (Error) -> Void){
let baseUrl = "your base URL"
let fullUrl = baseUrl + endPath
var headers = ["Content-type" : "multipart/form-data"]
if let header = header{
headers = header
}
let url = (try? URLRequest(url: fullUrl, method: .post, headers: headers))!
upload(multipartFormData: { (multipartData) in
for imagesData in dictImage {
for arrimage in imagesData.value{
multipartData.append(arrimage.jpegData(compressionQuality: 0.50)!, withName: imagesData.key, fileName: "\(Date().timeIntervalSince1970).jpg", mimeType: "image/jpeg")
}
}
for (key, value) in parameter {
multipartData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, with: url) { (resultData) in
switch resultData{
case .success(let upload, let streamingFromDisk, let fileURL):
print("File URL : \(String(describing: fileURL))")
print("Streaming From Disk : \(streamingFromDisk)")
upload.uploadProgress(closure: { (progress) in
print("Progress : \(progress.fractionCompleted)")
})
upload.responseJSON(queue: nil, options: .allowFragments, completionHandler: { (response) in
if let value = response.result.value
{
success(value)
}
})
case .failure(let error):
failure(error)
print(error)
}
}
}

Alamofire sending parameter array with key and multiple value

I need to do this in my project:
multiple values in multiple array common key for parameter
Some links that have the same question but no exact answers, I always see posts that have answers like use a custom encoding and that's it.
https://github.com/Alamofire/Alamofire/issues/570
i have 4 array :
var imagesArray: [UIImage] = [], var DayOpreation: [String] = [],varDayOffStart: [String] = [], var DayOffEnd: [String] = []
and this my code :
let parameters : Parameters = [
"about": self.descriptionLabel.text!,
"address" : addressLabel.text!,
"country" : "1",
"state": "1",
"city" : "1",
"postcode" : self.postalCode.text!,
"policies": self.policiesLabel.text,
"longitude" : "",
"latitude" : "",
"available_24hours": "0",
"open_hour" : "09:00",
"closed_hour" : "18:00",
"operating_days[0]": "Senin",
"days_off[0][start]" : "2019-10-10",
"days_off[0][end]" : "2019-10-15",
]
let token = UserDefaults.standard.string(forKey: UserDefaultConstant.ACCESS_TOKEN)
let headers = ["key": "\(token!)"
]
let ImageData = UIImageView()
ImageData.image = UIImage(named: "rectangle-1")
let imgData = UIImagePNGRepresentation(ImageData.image!)!
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "photo_profile[0]",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
},
to:"\(Endpoints.BASE)\(Endpoints.UPDATE_VENDOR)",
method: .post,
headers: headers,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
if let data = response.data {
guard let json = try? JSON(data: data) else { return }
let messageRoom = json["message"].string
print("listOfficialRoom== ",json)
}
}
case .failure(let encodingError):
print(encodingError)
}
})
Use Paramaters in Alamofire, something like this
let daysOff = [String: Any]() // array of dictionaries for days off
for (i, day) in days.enumerated() {
let dayOff: Parameters = [
"start": day.start,
"end": day.end
]
daysOff["\(i)"] = dayOff
}
let parameters: Parameters = [
"open_hour": "...",
"closed_hour": "...",
"days_off": daysOff
]

how to set multipart "withname" with dictionary in swift?

I want to send the images to the server with multipart form. Normal
image uploading is working with the multipart but facing the
problem is when I need to set withname with array inside dictionary.
alamofireManager.upload(multipartFormData: { multipartFormData in
for i in 0..<images.count {
let imgData = UIImagePNGRepresentation(images[i])!
multipartFormData.append(imgData, withName: "fileUpload",fileName: "\(images)i", mimeType: "image/png")
}
Server parameters are like
"documants" : [{
"documentType" : "Image",
"fileUpload: "" // multipart data
},{
"documentType" : "Image",
"fileUpload: "" // multipart data
}]
So how to mention the node name documents[0].fileUpload with withName using multipartFormData?
You can implement 'multipart' in this way...using Swift4.2
let headers: HTTPHeaders = [
/* "Authorization": "your_access_token", in case you need authorization header */
"Content-type": "multipart/form-data"
]
let url = try! URLRequest(url: baseURL, method: .post, headers: headers)
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(img, withName: "file", fileName: imgName, mimeType: "\(fileType ?? "jpg")")
}, with: url) { result in
switch result {
case .success(let upload, _, _):
upload.responseString { response in
switch (response.response?.statusCode)
{
case 200: //The request was fulfilled
print("Network - HandShaking Successfull...!!!")
debugPrint(response)
}
case .failure(let encodingError):
print(encodingError)
}
}
Hope you will get idea of 'multipart'...!!!

Swift 3 Alamofire POST with Headers Parameters, Query Parameters, and Request Body

I am faily new to Alamofire itself, so forgive me if this is a simple one.
I would like to post a bank account object to intuit payments using Alamofire, however I keep getting the following error:
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}
The documentation notes the following:
REQUEST URL
Sandbox Base URL: https://sandbox.api.intuit.com
Production Base URL: https://api.intuit.com
Operation: POST /quickbooks/v4/customers/<id>/bank-accounts
Content type: application/json
Header Parameters:
Request-Id required
Query Parameters:
id required
Request body
{
"name": "My Checking",
"routingNumber": "XXXXX0358",
"accountNumber": "XXXX4534",
"accountType": "PERSONAL_CHECKING",
"phone": "6047296480"
}
My attempts are as follows:
func saveBankAccountToIntuitPayments() {
let url = "https://api.intuit.com/quickbooks/v4/customers/" + userID! + "/bank-accounts"
let parameters: Parameters = [
"name": "John Doe",
"routingNumber": "123321456",
"accountNumber": "432123789012",
"accountType": "PERSONAL_CHECKING",
"phone": "55568925029"
]
ATTEMPT 1
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON(completionHandler: {
response in
print("running self.parseData(JSONData: response.data!)")
self.parseData(JSONData: response.data!)
})
ATTEMPT 2
let requestId = userID! + getTimeNow()
let header = [ "Request-Id" : requestId ]
Alamofire.request(url: url, method: .post, headers: header, parameters: parameters, encoding: JSONEncoding.default).responseJSON(completionHandler: {
response in
print("running self.parseData(JSONData: response.data!)")
self.parseData(JSONData: response.data!)
})
ATTEMPT 3
request(url, method: .post, parameters: parameters, headers: header).responseJSON(completionHandler: {
response in
print("running self.parseData(JSONData: response.data!)")
self.parseData(JSONData: response.data!)
})
}
This is the code for my json parser:
func parseData(JSONData: Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONStandard
print("printing readable JSON (below)")
print(readableJSON ?? "no JSON data was returned")
} catch {
print("errror occured (below)")
print(error)
}
}