I have POST request:
init (url: String,arg: String) {
self.responseString = nil
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
let postString = arg
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
guard let data = data, error == nil else {
print("error=\(error)")
self.responseString = nil
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { //
self.responseString = nil
} else {
self.responseString = String(data: data, encoding: .utf8)
}
}
task.resume()
}
When arg have a character \n, half arg text is lost. How fix this problem?
strUrl = strUrl.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
let url = URL.init(string: strUrl)
let requestURL = URLRequest(url: url!)
You need to add addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) method to allow URL Query.
Related
Trying to execute a call from Swift passing one parameter to PHP and getting the result
It does not execute the PHP call... not sure why?
func getInfo(_ dataValue:String){
print("in UserModel.getInfo")
let url: URL = URL(string: urlInfoPath)!
let rq = NSMutableURLRequest(url: url)
rq.httpMethod = "POST"
let postString = "a=\(dataValue)"
rq.httpBody = postString.data(using: String.Encoding.utf8)
print("PHP postString:", postString)
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) {
data, response, error in
print("UserModel.getINFO FROM PHP");
if error != nil {
print("error=\(String(describing: error))")
return
}
let val = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
self.responseString = val! as String
print("responseString = ", self.responseString)
}
}
I use this code and work perfect. I use swift. PHP is work fine.
I also try some other examples at this
I have 2 problems
first my responseString values turns in Optional("Success"). Why?
second is How can assign it on my button?
func makePostCall() {
var request = URLRequest(url: URL(string: "MyURL/page.php")!)
request.httpMethod = "POST"
let postString = "id=login"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
self.lbl.text = responseString
}
task.resume()
//return responseString
}
You need to use DispatchQueue.main.async to work with UI from URLRequests. Also you need to use [weak self] to prevent reference cycle problem. At last, btn.setTitle(responseString, for: .normal) to set title for button state .normal. Here is correct answer!
func makePostCall() {
var request = URLRequest(url: URL(string: "MyURL/page.php")!)
request.httpMethod = "POST"
let postString = "id=login"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) {[weak self] data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
guard let responseString = String(data: data, encoding: .utf8) else {
return
}
print("responseString = \(responseString)")
DispatchQueue.main.async {
self?.lbl.text = responseString
self?.btn.setTitle(responseString, for: .normal) // your button
}
}
task.resume()
//return responseString
}
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()
}
I'm trying to upload an image to the server. As for now, I get an error response which checks if name='image', and the error means that it's not. The line where I set it is this:
body.appendString("Content-Disposition: form-data; name='image'; filename='test.jpg'")
my full code of the POST request is this: I do get a 200 and the only problem is with the name parameter which I really can't figure out.
func imageUploadRequest()
{
let stringUrl = "http://88.162.41.55/app_backend/public/api/v1/image?_r=1836486547600309"
let URL = NSURL(string: stringUrl.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!
let request = NSMutableURLRequest(URL: URL)
request.HTTPMethod = "POST";
request.setValue("Bearer \(jwtToken)", forHTTPHeaderField: "Authorization")
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImageJPEGRepresentation(image, 1)
if(imageData == nil) {
print("image data is nil")
return
}
let body:NSMutableData = NSMutableData()
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name='image'; filename='test.jpg'")
body.appendString("Content-Type: image/jpg")
body.appendData(imageData!)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
request.HTTPBody = body
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(" response = \(responseString!)")
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
print("json", json)
} catch {
print("bad things happened")
}
}
task.resume()
}
Any ideas? Thank you so much!!
Sample NSURLSession
func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("Bearer ab-blah", forHTTPHeaderField: "Authorization")
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("path", forHTTPHeaderField: lePath)
let cursor:NSDictionary? = ["path":lePath]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
request.HTTPBody = jsonData
print("json ",jsonData)
} catch {
print("snafoo alert")
}
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let error = error {
completion(string: nil, error: error)
return
}
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
//print("Body: \(strData)\n\n")
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
completion(string: "", error: nil)
} catch {
completion(string: nil, error: error)
}
})
task.resume()
}
I am learning swift and I send a request to the server with the code below. It works for simple request and I get response from the server. My problem is I can not send a file to server.
code :
let parameters = parameter
let request = NSMutableURLRequest(URL: NSURL(string: requestUrl)!)
let boundaryConstant = "-----Boundary+\(arc4random())\(arc4random())"
let contentType = "multipart/form-data; boundary=" + boundaryConstant
let boundaryStart = "--\(boundaryConstant)\r\n"
let boundaryEnd = "--\(boundaryConstant)--\r\n"
let body:NSMutableString = NSMutableString();
for (key, value) in parameters {
body.appendFormat(boundaryStart)
body.appendFormat("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendFormat("\(value)\r\n")
}
body.appendFormat(boundaryEnd)
request.HTTPMethod = "POST"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else {
// check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
self.responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
print("MMMMMMMM \(self.responseString)")
self.result = self.responseString.dataUsingEncoding(NSUTF8StringEncoding)! as NSData
callback(self.responseString)
}
print("code start")
task.resume()
result :
i can post file to server by this code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let request = createRequest()
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
if error != nil {
// handle error here
print(error)
return
}
do {
if let responseDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
print("success == \(responseDictionary)")
}
} catch {
print(error)
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
}
task.resume()
}
func createRequest () -> NSURLRequest {
let param = []
let boundary = generateBoundaryString()
let url = NSURL(string: "URl")!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.setValue("userValue", forHTTPHeaderField: "X-Client-user")
request.setValue("passValue", forHTTPHeaderField: "X-Access-pass")
//let path1 = NSBundle.mainBundle().pathForResource("voice", ofType: "png") as String!
request.HTTPBody = createBodyWithParameters(param, filePathKey: "voice", paths: ["pathURl"], boundary: boundary)
return request
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, paths: [String]?, boundary: String) -> NSData {
let body = NSMutableData()
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
if paths != nil {
for path in paths! {
let url = NSURL(fileURLWithPath: path)
let filename = url.lastPathComponent
let data = NSData(contentsOfURL: url)!
let mimetype = mimeTypeForPath(path)
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename!)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(data)
body.appendString("\r\n")
}
}
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
func mimeTypeForPath(path: String) -> String {
let url = NSURL(fileURLWithPath: path)
let pathExtension = url.pathExtension
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension! as NSString, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
return mimetype as String
}
}
return "application/octet-stream";
}
As you read here, you should use NSURLSession for HTTP work, it far more flexible and powerful; and I think is destined to replace NSURLconnection...
https://www.objc.io/issues/5-ios7/from-nsurlconnection-to-nsurlsession/
Here is a example for you...
func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("Bearer ab-blah-blah", forHTTPHeaderField: "Authorization")
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("path", forHTTPHeaderField: lePath)
let cursor:NSDictionary? = ["path":lePath]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
request.HTTPBody = jsonData
print("json ",jsonData)
} catch {
print("snafoo alert")
}
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let error = error {
completion(string: nil, error: error)
return
}
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)\n\n")
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
self.jsonParser(jsonResult,field2file: "ignore")
for (key, value) in self.parsedJson {
print("key2 \(key) value2 \(value)")
}
completion(string: "", error: nil)
} catch {
completion(string: nil, error: error)
}
})
task.resume()
}
Great answer above.. Here it's updated for Swift3:
func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("Bearer ab-blah-blah", forHTTPHeaderField: "Authorization")
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("path", forHTTPHeaderField: lePath)
let cursor:NSDictionary? = ["path":lePath]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
request.HTTPBody = jsonData
print("json ",jsonData)
} catch {
print("snafoo alert")
}
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let error = error {
completion(string: nil, error: error)
return
}
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)\n\n")
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
self.jsonParser(jsonResult,field2file: "ignore")
for (key, value) in self.parsedJson {
print("key2 \(key) value2 \(value)")
}
completion(string: "", error: nil)
} catch {
completion(string: nil, error: error)
}
})
task.resume()
}