How to send or upload image file with patch method on JSON server? swift - swift

I want to send file of image on server when I edit choose image button, but I don't know why my image profile didn't update on sever , here is my console debugger area when app run :
and also I have this message from server that "please upload an image"
this response should change to "your profile photo updated" and also this my code :
func imageInput(asset : String) {
let semaphore = DispatchSemaphore (value: 0)
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + asset
let parameters = [
[
"key": "image",
"src": "\(path)",
"type": "file"
]] as [[String : Any]]
let boundary = "Boundary-\(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
print("params image key is \(paramName)")
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
print("value of param is \(paramValue)")
body += "\r\n\r\n\(paramValue)\r\n"
} else {
if path != nil {
body += "; filename=\"\(path)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n \(path)\r\n"
print("this is going to true")
}
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://api.offernews.co/api/user")!,timeoutInterval: Double.infinity)
request.addValue("baerar \(profileKeychain["token"]!)", forHTTPHeaderField: "Authorization")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "PATCH"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data
else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
}
and also this is my another question like this that every code that you want on this link Photo did not update when I patch it to json server swift
thanks guys

Related

Swift 5 - UrlSession - Post request starts with array

I am new about Swift. And I have question.I have to post a request starts with an array.
like this:
[{"columnName":"","columnLogic":"LIKE","columnValue":""}]
I tried with postman and return value which I wanted to.
Normally if it doesn't start with "[" and then I can post request and get back value. But Start with "[" and I tried many things not succeded :( please help me! I add my code which I use starts with "{" json post, this codes return error.`
private func getDataCars(){
struct Result: Codable {
let status: String
let document: DocumentStruct
}
struct DocumentStruct : Codable {
let pageno: Int
let total_count: String
let records: [RecordStruct]
}
struct RecordStruct: Codable{
let user_id:String
let user_name:String
let user_mail:String
let user_password:String
let user_phone:String
let user_durum:String
}
let parameters = [["columnName": "nameofcolumn", "columnLogic": "LIKE", "columnValue": "searchstring"]]
let url = URL(string: "http://getapiadress")!
let AuthTokenString = "somekey"
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("Bearer " + AuthTokenString, forHTTPHeaderField: "Authorization")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to data object and set it as request body
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request, completionHandler: { data, response, error in
guard error == nil else {return}
guard let data = data else {return}
var result: Result?
do{
result=try JSONDecoder().decode(Result.self, from: data)
}
catch{
print("failed")
print(error)
}
guard let json = result else {
return
}
print(json.document.records[0].car_marka)
})
task.resume()
}`
here is my response of post request:
{
"status": "success",
"code": 1,
"message": "users found",
"document": {
"pageno": "1",
"pagesize": "30",
"total_count": "1",
"records": [
{
"user_id": "1",
"user_name": "Boss",
"user_mail": "boss#boss.com",
"user_password": "boss",
"user_phone": "123456789",
"user_durum": "admin"
}
]
}
}
If you want to send a dictionary as you mentioned at the beginning but you get a run-time error while trying to declare a JSON variable in XCode
[{"columnName":"","columnLogic":"LIKE","columnValue":""}]
Then in your code, you can do like this
// this is the dictionary format in Swift
let parameters = ["columnName": "","columnLogic": "LIKE","columnValue": ""]
do {
// This step will convert your dictionary to jsonData
let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
request.httpBody = jsonData
} catch let error {
print(error.localizedDescription)
}
BUT Then if you want to make a POST request with an Array of objects then you can do something like this
struct ColumnInfo: Codable {
let columnName: String
let columnLogic: String
let columnValue: String
}
let parameters = [ColumnInfo(columnName: "nameofcolumn", columnLogic: "LIKE", columnValue: "searchstring")]
let url = URL(string: "http://getapiadress")!
let AuthTokenString = "somekey"
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("Bearer " + AuthTokenString, forHTTPHeaderField: "Authorization")
do {
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
request.httpBody = try jsonEncoder.encode(parameters) // pass dictionary to data object and set it as request body
} catch let error {
print(error.localizedDescription)
}

Multiple File Upload in Swift

I am trying to upload multiple file to the server by my iPhone. The problem is that when I try to upload 1.4 mb file it could not upload properly. I checked the uploaded file and the file size is 1 kb. So I made this code based on the postman. As you know the postman can create the code according to which language do you want. Thank you.
function uploadFile(){
var parameters: [[String: Any]] = []
var fileCount: Int = 0
let homeDirectory = ""
var soundPath = "\(homeDirectory)\(CommonUtil.PATH_SOUND)"
soundPath = soundPath.replacingOccurrences(of: "file:///", with: "")
//fiels[0] = ["fileName" : "2021_10_19_09_12_52.wav"]
//fiels[1] = ["fileName" : "2021_10_19_09_12_53.wav"]
//fiels[3] = ["fileName" : "2021_10_19_09_12_54.wav"]
for item in files{
var dict = item as! [String:String]
let strFilePath = "\(soundPath)\(dict["fileName"]!)"
if FileManager.default.fileExists(atPath: strFilePath){
var dict = [String:Any]()
dict.updateValue("strFileName[\(fileCount)]", forKey: "key")
dict.updateValue(strFilePath, forKey: "src")
dict.updateValue("file", forKey: "type")
parameters.append(dict)
fileCount++
}
print(dict["fileName"]!)
}
var dict = [String:Any]()
dict.updateValue("strApiName", forKey: "key")
dict.updateValue("soundFileUpload", forKey: "value")
dict.updateValue("text", forKey: "type")
parameters.append(dict)
uploadFiles(parameters: parameters)
}
func uploadFiles(parameters: [[String: Any]]){
var semaphore = DispatchSemaphore(value: 0)
let boundary = "Boundary - \(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
body += "\r\n\r\n\(paramValue)\r\n"
} else {
let paramSrc = param["src"] as! String
//let fileData = URL(string: paramSrc)?.dataRepresentation ?? Data()
let fileData = try! NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)
body += "; filename=\"\("file:///"+paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "http://api.polytus.com/")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
DispatchQueue.main.async {
self.showLoading(show: false)
self.showBluetoothAlert(message: "failed")
}
print(String(describing: error))
semaphore.signal()
return
}
DispatchQueue.main.async {
self.showLoading(show: false)
self.showBluetoothAlert(message: "success")
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
}
For what I've understand you want to know the file size in the server filesystem. If this is you want you have to use an API that give you back the data, after the file is uploaded and moved from temporary web server space to final location. In brief you need to do 2 request, one for upload and one for getting the file data (space or any other data needed), or develop an API that give you as answer of the correct upload the file size.

How to make a url post request which is returned by the function in Swift

Hi guys I am trying to contact my Rest API and get the data. I am successful in doing that but I want the function to return the string that it obtained.
This is why code so far:
private func getPost(one: String, two: String, link: String) {
let url = URL(string: link)!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let parameters: [String: Any] = [
"parent" : one,
"original": two
]
request.httpBody = parameters.percentEncoded()
var responseString = ""
print("Sarcasm \(yourMessage) \(otherMessage) \(link)")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else { // check for fundamental networking error
print("error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
responseString = String(data: data, encoding: .utf8)!
print("responseString = \(responseString)")
// return responseString
}
task.resume()
}
Where :
extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
All I want is this function (getPost) to return the response string that it obtains from the post request. However, I do not know what to do. I mean the application gets the response string from the post request but then I want to modify the function so that it returns it instead of printing it.

Swift 4.2 code equivalent for SAP's Leonardo API [duplicate]

This question already has answers here:
Upload image with parameters in Swift
(3 answers)
Closed 4 years ago.
Getting HTTP 400 error while connecting with SAP Leonardo sandbox server using scene text recognition API
SAP provides boilerplate code in older version of swift. I have used curl command and the API and works. But its not working when I try and convert the code into swift 4.2 version. I am attaching the code below.
func connectWithSAP(photoURL : URL, photoData : String, sentImageData : Data){
if let myNewURL = URL(string: "https://sandbox.api.sap.com/ml/scenetextrecognition/scene-text-recognition") {
var myRequest = URLRequest(url: myNewURL)
myRequest.addValue("multipart/form-data; --\(boundary)", forHTTPHeaderField: "Content-Type")
myRequest.addValue("application/json", forHTTPHeaderField: "Accept")
myRequest.addValue("xxxxxxxxxxx", forHTTPHeaderField: "APIKey")
myRequest.httpMethod = "POST"
myRequest.cachePolicy = .reloadIgnoringLocalCacheData
myRequest.timeoutInterval = 60.0
// Constructing the body of the request.
var data = Data()
var dataString = ""
dataString.append("--\(boundary)\r\n")
dataString.append(contentsOf: "Content-Disposition:form-data; name=\"files\"; filename=\"Image1.jpeg\" \r\n")
dataString.append(contentsOf: ";Content-Type:image/jpeg \r\n\r\n")
dataString.append(photoData)
dataString.append("--\(boundary) ----- \r\n")
data = dataString.data(using: .utf8)!
myRequest.httpBody = data
let task = URLSession.shared.dataTask(with: myRequest) { (data, response, error) in
if let error = error {
print(error)
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print(error as Any)
// Getting output at this stage, which is shown below
return }
if let mimeType = httpResponse.mimeType,
mimeType == "application/json",
let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any]
print(json as Any)
}catch {
print(error)
}
}
}
task.resume()
}
I am getting a following details in my response object
{ URL: https://sandbox.api.sap.com/ml/scenetextrecognition/scene-text-recognition } { Status Code: 400, Headers {\n Connection = (\n \"keep-alive\"\n );\n \"Content-Length\" = (\n 131\n );\n \"Content-Type\" = (\n \"application/json\"\n );\n Date = (\n \"Sat, 16 Feb 2019 11:56:37 GMT\"\n );\n Server = (\n \"Werkzeug/0.14.1 Python/3.5.5\"\n );\n \"Strict-Transport-Security\" = (\n \"max-age=31536000; includeSubDomains; preload;\"\n );\n \"X-Vcap-Request-Id\" = (\n \"fea7037c-4e48-49d2-4be1-53b0dad0ee46\"\n );\n}
As you would see the status code is HTTP 400. Need some help in getting the right response and data from the server.
Most probably, the body data got messed up. Here's the working code:
let boundaryConstant = "----WebKitFormBoundary7MA4YWxkTrZu0gW"
let headers = [
"APIKey": "YourAPIKEY"
]
let contentType = "multipart/form-data; boundary=" + boundaryConstant
//API endpoint for API sandbox
var request = URLRequest(url: URL(string: "https://sandbox.api.sap.com/ml/scenetextrecognition/scene-text-recognition")!)
//setting request method
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let path1 = Bundle.main.path(forResource: "your_image", ofType: "png")!
let url = URL(fileURLWithPath: path1)
let fileName = url.lastPathComponent
let data = try? Data(contentsOf: url)
let imageData = UIImage.init(data: data!)!
let pngData = UIImagePNGRepresentation(imageData)!
let mimeType = "image/png"
let boundaryStart = "--\(boundaryConstant)\r\n"
let boundaryEnd = "--\(boundaryConstant)--\r\n"
let fieldName = "files"
let contentDispositionString = "Content-Disposition: form-data; name=\"\(fieldName)\"; filename=\"\(fileName)\"\r\n"
let contentTypeString = "Content-Type: \(mimeType)\r\n\r\n"
var body = Data()
body.append(boundaryStart.data(using: .utf8)!)
body.append(contentDispositionString.data(using: .utf8)!)
body.append(contentTypeString.data(using: .utf8)!)
body.append(pngData)
body.append("\r\n".data(using: .utf8)!)
body.append(boundaryEnd.data(using: .utf8)!)
request.httpBody = body
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
request.setValue(String(body.count), forHTTPHeaderField: "Content-Length")
let dataTask = session.dataTask(with: request) { (data, response, error) in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
}
dataTask.resume()
You can also use Alamofire to upload image. It's way cleaner, don't need to play around with "body" much:
let headers: HTTPHeaders = [
"APIKey": "<<Your API KEY>>",
"Content-type": "multipart/form-data"
]
let parameters:[String: String] = [:] //any other parameters you need to send
let path1 = Bundle.main.path(forResource: "<<your_image>>", ofType: "<<png or jpeg>>")!
let url = URL(fileURLWithPath: path1)
let fileName = url.lastPathComponent
let data = try? Data(contentsOf: url)
let imageData = UIImage.init(data: data!)!
//converting it into png data
let pngData = UIImagePNGRepresentation(imageData)
let mimeType = "image/png"
let fieldName = "files"
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 = pngData{
multipartFormData.append(data, withName: fieldName, fileName: fileName, mimeType: mimeType)
}
}, usingThreshold: UInt64.init(), to: "https://sandbox.api.sap.com/ml/scenetextrecognition/scene-text-recognition" , method: .post, headers: headers) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded")
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
}
}

urlrequest not sending post request

Hi i am new to IOS App developement.
My code is
func sendRequest<T: Decodable>(api: String, parameters: [String: String]? = nil, outputBlock: #escaping (T) -> () ) {
guard let url = URL(string: "http://xxyyzz.com/appRegister.php") else {return}
print("hitting : -", url.absoluteString)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let newparam = ["name": "rr", "pass": "123456", "email": "rr#rr.com", "passConfirm":"123456"]
let httpBody = try? JSONSerialization.data(withJSONObject: newparam)
request.httpBody = httpBody
if let data = request.httpBody, let str = String(data: data, encoding: String.Encoding.utf8) {
print(str)
}
URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
DispatchQueue.main.async {
Indicator.shared.hideProgressView()
if let err = error {
print(err.localizedDescription)
return
}
guard let data = data else {return}
do {
let obj = String(data: data, encoding: String.Encoding.utf8)
print(obj ?? "oberrrrr")
}
}
}.resume()
}
and console printed result as per code is below
hitting : - http://xxyyzz.com/appRegister.php
{"email":"rr#rr.com","passConfirm":"123456","name":"rr","pass":"123456"}
{"error":"Please enter all fields."}
url and parameters works well on postman that means their is something missing in my code.
just to answer the problem if anyone else faces this.
this code is fine but the problem was with php web-service as the backend developer was not accepting json values as parameter instead form data was need to send.
So, two types of fix can be made here
accept json at backend by adding :-
$postdata = file_get_contents("php://input");
$request = json_decode($postdata, true);
send form data instead json
func sendRequest<T: Decodable>(api: String, parameters: [String: Any]? = nil, outputBlock: #escaping (T) -> () ) {
guard let url = URL(string: api) else {return}
print("hitting : -", url.absoluteString)
var request = URLRequest(url: url)
if let parameters = parameters {
request.httpMethod = "POST"
var postArr = [String]()
for(key, value) in parameters
{
postArr.append(key + "=\(value)")
}
let postString = postArr.map { String($0) }.joined(separator: "&")
request.httpBody = postString.data(using: .utf8)
if let data = request.httpBody, let str = String(data: data, encoding: String.Encoding.utf8) {
print(str)
}
}
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
Indicator.shared.hideProgressView()
if let err = error {
print(err.localizedDescription)
return
}
guard let data = data else {return}
do {
let obj = try JSONDecoder().decode(T.self, from: data)
outputBlock(obj)
} catch let jsonErr {
print(jsonErr)
}
}
}.resume()
}