I am trying to send multipart image data using Alamofire with [String:Any] parameters ,i am only able to to post [String:String] parameters only
For [String:String] is doing like https://stackoverflow.com/a/40440371/4466607
but now i have to post like :
[ PayLoad ] and i have to send Image with image key which, i am already doing .
In postman it is working fine
Question :
How can i post image with Dictionary type [String:Any] in Swift
Please help
If your value is Any type then check this may be it helps you.
for (key, value) in params {
let paramsData:Data = NSKeyedArchiver.archivedData(withRootObject: value)
formData.append(paramsData, withName: key)
}
Rough solution:
If you insist on put Image data into a dictionary, you could convert image data to Base64 code, and then put Base64 string in the dictionary. You will submit a big JSON to the server. I don't think it's a good solution.
Better solution:
Another WebApi to submit images data, and that API will return uploaded images URL like https://www.example.com/image1234.jpg, or just return image id like "1234" which can be embedded to a URL lately. Finally, you submit the JSON data with image URL or id like {"image":"https://www.example.com/image1234.jpg"} or {"image":1234}.
Related
I am developing iOS app, I am using URL Session method for make API calls. Api response gives one property which contains AWS s3 link for pdf document.
What should happen:
So in this app, I am retrieving a PDF document from the server to view in the app, so in the GET URL that I'm sending will give a response of an access link of the pdf document generated through AWS S3.
What is happening now:
Document name: Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf (notice there is an '&' sign)
In the android and Swagger application, this GET URL is working perfect on any circumstances.
but in the iOS version- in the URL session, when ever when there is a '&' sign inside the document's name, the responding access link gets corrupted.
Now in Android and Swagger, when we are accessing the same document, it works perfectly, but for iOS it doesn't.
URL that doesn't work on iOS but that works in Android and Swagger:
https://domainName/api/FileUpload/GetDocumentUrl?S3Key=**Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf**&fileCategory=2&userId=9888900000
Above url having parameter name called 'S3Key' value is Document/sdd3343 sfnf0asdnd0UserB&ServiceLetter.pdf and it having an ampersand '&' symbol in middle of the name.
iOS response for the above URL:
{"success":true,"response":"https://samplesite.s3.ap-southwest-2.amazonaws.com/Document/sdd3343-sfnf0asdnd0UserB?X-Amz-Expires=3600&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAWEWNDEFIENS88NKWSWIULHKA/20221010/ap-southwest-2/s3/aws4_request&X-Amz-Date=20221010T011135Z&X-Amz-SignedHeaders=host&X-Amz-Signature=44cab95333c0b5e385959835948539845948023823483","error":null}
In here you can see the response which got by the URL Session. But the reponse url body cut off from ampersand symbol.
Current Response: /Document/sdd3343-sfnf0asdnd0UserB?X-Amz-Expires=3600&X.........
Expected Response: /Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf?X-Amz-Expires=3600&X.........
How to solve this URL Session problem
Note how & characters are used to separate key/value pairs in a URL. Because of this, you cannot have an & in the middle of a value within a URL, because it is interpreted as a delimiter before the next key/value pair. The answer is to percent-escape the & in the value associated with the S3Key key. To do this, the easiest way is URLComponents:
guard var components = URLComponents(string: "https://domainName/api/FileUpload/GetDocumentUrl") else {
print("URLComponents failure")
return
}
components.queryItems = [
URLQueryItem(name: "S3Key", value: "Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf"),
URLQueryItem(name: "fileCategory", value: "2"),
URLQueryItem(name: "userId", value: "9888900000")
]
guard let url = components.url else {
print("unable to build url")
return
}
print(url) // https://domainName/api/FileUpload/GetDocumentUrl?S3Key=Document/sdd3343-sfnf0asdnd0UserB%26ServiceLetter.pdf&fileCategory=2&userId=9888900000
There are other ways to manually percent-escape the values in the URL, but URLComponents does it reasonably gracefully.
I have created a Dictionary with some values. I want to create JSON string of that dictionary object.
I am using String(data: data, encoding: .utf8)! to create json string but every time i run this code i am getting json string in diffrent sequence and order of same data.
import Foundation
import CommonCrypto
var object = ["emp1":["name":"neeraj","age":"14","degree":"Btech"],
"emp2":["name":"ajay","age":"24","degree":"Mca"],
"emp3":["name":"vijay","age":"34","degree":"Bca"],
"emp4":["name":"raju","age":"44","degree":"Mtech"]]
if let data = try? JSONSerialization.data(withJSONObject: object, options: []){
print(String(data: data, encoding: .utf8)!)
}
First time result:
{"emp2":{"age":"24","degree":"Mca","name":"ajay"},"emp4":{"age":"44","name":"raju","degree":"Mtech"},"emp3":{"degree":"Bca","name":"vijay","age":"34"},"emp1":{"degree":"Btech","name":"neeraj","age":"14"}}
Second time result:
{"emp1":{"age":"14","degree":"Btech","name":"neeraj"},"emp4":{"name":"raju","degree":"Mtech","age":"44"},"emp3":{"name":"vijay","age":"34","degree":"Bca"},"emp2":{"name":"ajay","age":"24","degree":"Mca"}}
I want same result for every time.
I need same order to create md5 checksum to compare with recieved checksome of data.
I am getting a response from web service
for e.g
{
"payload":{
"object1":["name":"neeraj"],
"object2":["name":"ajay"]
},
"hash":"<hash of payload using md5>"
}
i have to create an md5 hash at my side and need to verify with hash i recieved.
but when i create JSON String i got different order and my hash doesn't match with recieved hash.
Please help
Don't use MD5 it's broken.
Create your dictionary from the JSON parse and then instantiate objects from that dict.
Hash the objects with a sensible digest such as Keccak, SHA-2, SHA-3 or Blake2.
I have to send a JSON file that I collect on my iOS to my backend team. The JSON looks something like:
{
"samples" : [
{
"acw" : 11,
"e_reserved" : 0,
"acc" : 28,
"cheat_rate" : 16,
}
]
}
I am making a post request to backend at:
http://make-post.com/api/post-activities
The backend expects the JSON as:
/api/post-activities/
Request Body
The request body should be a "application/json" encoded object,
containing the following items.
Parameter Description
name
time_stamp
duration
We do not collect all these data ourselves but backend has to process the data we supply and get those info.
What I tried first was to put all these data in an online storage and create a request as:
Request: {“pod_id”:“F11”,“type”:“Normal Activity”,“time_stamp”:“2019-04-17T22:29:35.147Z”,“url”:“https:\/\/s3.amazonaws.com\/mybucket-test\/myid#gmail.com\/2019-04-17\/d9335.json”}
But when I send request like this, I get Status Code 400 error.
So my next idea was to pass the whole JSON I collect to them. Upon doing that, they can get the data and see it in there database even though I get 500 error. Does it mean it is not really working?
The question is unclear to me, The learnings I have learnt you have some data that you want to pass to backend, and the backend sends 400 as you are not meeting his desire.
Suppose you have three variables to pass , let name,time_stamp, duration.
All you need to do in Swift, use Codable protocol.
class postJSON : Codable {
var name : String?
var time_stamp : String? // it may be Int64 according to backend what accept
var duration : String? // it may be Int64 according to backend what accept
}
While making a post request just do
let encodedData = try? JSONEncoder().encode(postJSON)
In my application I have used the same keyname to get data everywhere, now in json response that data is same but in one place the keyname is changed so I want to rename the keyname of the array in my json this is what I am getting searched on stack overflow but unable to find any reliable way please guide me any good way to do it
{"status":"success","msg":"deleted","pro_data":[]}
I want JSON with these keys:
{"status":"success","msg":"deleted","Images":[]}
you can use Codable to create JSON model and in that you can customise you key.
I assume your JSON response ({"status":"success","msg":"deleted","pro_data":[]}) available in Data format.
So, See the following code which are used to create JSON model for your data.
struct WSModel: Codable {
var status : String?
var msg : Int?
var Images : [Any]?
enum CodingKeys: String, CodingKey {
case currentPage = "status"
case msg = "msg"
case Images = "pro_data"
}
}
Due to there aren't any data type inside your array I have keep Any type of data.This code is work for when keys in response are "status", "msg", "pro_data".
Try this code and let me know still an issue. I hope this will work for you.
I assume your issue is that you want to continue to use "Images":[] key, without having to change rest of your code.
In your JSON response that you want to change, you can try something like this.
response["Images"] = response["pro_data"]
I have an app, where user can import any type of files as many as he wants and after that he should be able to send them to server. User can attach picked images from gallery, taken photos from camera, and any files using UIDocumentPickerViewController
This is the point where I'm struggling. I can't figure out how to send these files to the server using Alamofire or any other way.
While googling I found examples of how to send images, mainly one image, which is not quite suitable for my project, also there is mimeType you should state, which is not good for 20 different filetypes.
Example:
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: "image", fileName: "image.png", mimeType: "image/png")
}
I have also studied Alamofire documentation and found methods to send files, but I could not make it running. I simply don't understand what should I place after forResource and withExtension. I tried to place file URL and file extension but it failed to send files.
let fileURL = Bundle.main.url(forResource: "video", withExtension: "mov")
Alamofire.upload(
fileURL, to: serverLink).responseJSON { response in
debugPrint(response)}
I would be grateful if anyone could guide me, or even better provide some code examples.
Sorry for long question, and thank you for your attention and time!