I have read all the other threads but my problem is a mix of those. So I am trying to send some content over to a php server through HTTP in swift. Everything works fine until I append an image base64 content to the body of the http tag. I checked the php backend max post size, wasnt it. I copy pasted the image content that was generated in swift and pasted it in chrome and image was there, so image is not faulty.
This is the sample code of what I have
let url = NSURL(string: "https:example.com/endpoint")
// let session = NSURLSession.sharedSession();
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
var body = "csrf_token=" + (token.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())! as String)
body += "&email=" + (email?.text)!
body += "&first_name=" + (firstName?.text)!
body += "&last_name=" + (lastName?.text)!
body += "&password=" + password!.text!
//body += "&image_content=" + imageContent
body += "&confirm_password=" + confirmPassword!.text!
body += "&provider=" + provider
body += "&pictureURL=" + pictureURL
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
request.addValue("https:example.com/", forHTTPHeaderField: "origin")
request.addValue("https:example.com/endpoint", forHTTPHeaderField: "referrer")
let task = session.dataTaskWithRequest(request) {
(
let data, let response, let error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error")
print(data)
print(response)
return;
}
let dataString = NSString(data :data!, encoding: NSUTF8StringEncoding);
print(dataString)
if ((response as! NSHTTPURLResponse).statusCode == 200) {
dispatch_async(dispatch_get_main_queue(), {
self.performSegueWithIdentifier("loginAfterSignup", sender: nil)
})
}
else {
dispatch_async(dispatch_get_main_queue(), {
print((response as! NSHTTPURLResponse).statusCode)
print("error code, could not sign up and login")
})
}
}
task.resume()
So when I uncomment the line with the base64 string content, I go to the throwback call and it prints the "error".
I have no clue why its not sent through http. Is there a rule I have to obey? Do I have to set a certain http header once I append a large string? Am I missing something here?
Thanks
Yep, it was a stupid Apache settings error. I have previously modified max_post_size and got nothing. However this time I modified the max request body parameter and I could finally send data to the server.
Related
func convertImageToBase64(image: UIImage) -> String {
let imageData = UIImagePNGRepresentation(image)
let base64String = imageData?.base64EncodedString(options:.lineLength64Characters)
return base64String!
}// end convertImageToBase64
Swift code is here (base 64 encode part) :
let base64string = self.convertImageToBase64(image: self.pro_images.image!)
let imgbase64str = base64string.replacingOccurrences(of:"+", with: "%2B")
request.httpMethod = "POST"
let postString = ("email=\(savedValue!)&image=\(imgbase64str)&subject=\(self.analy_title.text!)&content=\(self.analy_text.text!)")
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, ....
php code is here :
if($image != "null"){
if(file_put_contents($upload_path,base64_decode($image))){
I want to upload my base64 encode image
but I can't got original picture.
because picture is not display.
How to solve this problem ?
Im encrypting a string in PHP using the following code
<?php
$key256 = "323";
$iv128 = "2424";
$text = "ABC";
$blocksize = 16;
$len = strlen($text);
$pad = $blocksize - ($len % $blocksize);
$text .= str_repeat("0", $pad);
$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key256, $text, MCRYPT_MODE_CBC, $iv128);
echo $cipher;
?>
In SWIFT I use POST Request and get the data from the server and print out the fetched data to the console like this
var request = URLRequest(url: URL(string: "http://www.example.com/test.php")!)
request.httpMethod = "POST"
let akey:String = txt_key.stringValue;
let email:String = txt_email.stringValue
let VAL:String="test"
var data="blah"
let postString = data
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)
}
task.resume()
This keeps printing nil even when the Web Browser shows the encrypted string.
What I'm I doing wrong?
Update
I have set the app transport security and stuff in the info.plist and the printing works correctly if I don't use encryption in php
I am trying to sent input from the user to a php script to have it ultimately passed to an SQL server, Most of the code runs but having problem with submitting the data.
#IBAction func submit(_ sender: AnyObject) {
let requestURL = URL(string: "*****")
let request = NSMutableURLRequest(url:requestURL!)
request.httpMethod = "POST"
let song=txt1.text!
let artist=txt2.text!
let album=txt3.text!
let year=txt4.text!
let genre=txt5.text!
let songPost = "song=" + (song as String)
let artistPost = "&artist=" + (artist as String)
let albumPost = "&album=" + (album as String)
let yearPost = "&year=" + (year as String)
let genrePost = "&genre=" + (genre as String)
request.httpBody = songPost.data(using: String.Encoding.utf8);
request.httpBody = artistPost.data(using: String.Encoding.utf8);
request.httpBody = albumPost.data(using: String.Encoding.utf8);
request.httpBody = yearPost.data(using: String.Encoding.utf8);
request.httpBody = genrePost.data(using: String.Encoding.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)")
print(response)
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)")
}
task.resume()
Having an issue with the urlsession.shared.datatask line of code. Compiler error says "ambigious reference to member'dataTask(with:completionhandler:)"
What can get this code to work and how can I verify that this information was passed on the app?
The reason you get that error message is because you are passing NSMutableURLRequest where URLRequest is needed.
Changing this line:
let request = NSMutableURLRequest(url:requestURL!)
to this:
var request = URLRequest(url:requestURL!)
should fix it.
But I recommend a little more fixes to make your request successfully sent to the server:
let requestURL = URL(string: "*****")
//You should use `URLRequest` in Swift 3, mutability is represented by `var`
var request = URLRequest(url:requestURL!)
request.httpMethod = "POST"
//UITextField.text can be nil, you should treat nil cases
//(Generally avoid using forced unwrapping `!` as far as you can.)
let song = txt1.text ?? ""
let artist = txt2.text ?? ""
let album = txt3.text ?? ""
let year = txt4.text ?? ""
let genre = txt5.text ?? ""
//`song`,... are all Strings, you have no need to add `as String`
let songPost = "song=" + song
let artistPost = "&artist=" + artist
let albumPost = "&album=" + album
let yearPost = "&year=" + year
let genrePost = "&genre=" + genre
//You need to make a single data containing all params
//(Creating a concatenated String and getting `data` later would be another way.)
var data = Data()
data.append(songPost.data(using: String.Encoding.utf8)!)
data.append(artistPost.data(using: String.Encoding.utf8)!)
data.append(albumPost.data(using: String.Encoding.utf8)!)
data.append(yearPost.data(using: String.Encoding.utf8)!)
data.append(genrePost.data(using: String.Encoding.utf8)!)
request.httpBody = data
let task = URLSession.shared.dataTask(with: request) { data, response, error in
...
I am trying to send an image to server, but the image should be in Base64 format. I am using this function to send it:
func upload_signature_staff(ticket: NSString){
let defaults = NSUserDefaults.standardUserDefaults()
let stringOne = defaults.stringForKey(defaultsKeys.staff_id)
let stringtwo = defaults.stringForKey(defaultsKeys.mst_customer)
let sig = defaults.stringForKey("staff_signature")
let request = NSMutableURLRequest(URL: NSURL(string: "http://xxxxxxxxxxxxx/upload.php")!)
request.HTTPMethod = "POST"
let postString = "action=add_signature&mst_customer=\((stringtwo!))&ticket=\((ticket))&signature=\((sig!))¤t_user=\((stringOne!))&item_type=10"
print(postString)
request.HTTPBody = postString.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)")
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
//self.performSegueWithIdentifier("goto_main2", sender: self)
}
The sig variable holds the Base64 string, it is being printed in my console so I can verify that the string is correct. I am also printing the postString and upon inspection it is also correct that the signature is matching the Base64 String. But when I open phpmyadmin, I see the field of my image with incomplete Base64 string, maybe 1/4 is just there.
Here's my php code, in case you want to see it:
<?php
require_once("../c.php");
$action = trim($_POST['action']);
if($action == "add_signature"){
$mst_customer = trim($_POST['mst_customer']);
$ticket = trim($_POST['ticket']);
$signature = trim($_POST['signature']);
$current_user = trim($_POST['current_user']);
$item_type = trim($_POST['item_type']);
$inputtime = time();
$sql = "INSERT INTO ticket_items SET mst_customer = '$mst_customer', ticket = '$ticket', ticket_item_type = '$item_type', details = '$signature', addedby = '$current_user', lastupdate = '$inputtime' ";
mysql_query($sql) or die(mysql_error());
}
?>
I think this was solved in the comments but here's a recap:
Inserting base64 strings that were too long (variable length?) in a varchar(255) field resulted in missing data. As far as I can tell, increasing the size of the field solved the immediate problem. I use the term "immediate" because, as #YvesLeBorg pointed out in the comments, this is bound to fail at some point without input size restrictions on the backend.
Additionally, I couldn't ignore the fact that the PHP/SQL code was wide open to injections.
Passing $mst_customer = trim($_POST['mst_customer']); on to "INSERT INTO ticket_items SET mst_customer = '$mst_customer' and then executing via mysql_query($sql) or die(mysql_error()); is dangerous!
Anybody could write anything in the $_POST parameter and SQL would happily accept it. Prepared statements, PDO, input sanitization etc. are there for a reason.
Finally, there was an issue concerning vanishing + signs in the base64 data. This was the result of missing url encoding of the post data.
I think that sums it up.
I am trying to work with a swift code to pass vars to php and a response back to swift. this all goes smooth with the following code. This is just a simple peice of code to get things going. It gives me the correct connection and results, how ever i have to pass loads of data which should be in an array i guess. But when i try to send through more data in a array i don't see anything. In php i would explode the results to get them one by one but how do i get loads of values to variables so i can use them again?
below is my code
<?php
require('conn.php');
header('Content-type: application/json');
if($_POST) {
$database =trim ($_POST['database']);
$engine = trim($_POST['engine']);
$name = "William";
$results = Array("name" => $name
);
echo json_encode($results);
}/*end if POST*/
?>
this is the swift code
let data:NSString = ("bfdprofile" as NSString)
let engine:NSString = "account" as NSString
self.usernameLabel.text = prefs.valueForKey("USERNAME") as? String
let url = NSURL(string:"xxxxx.php")
let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
var request = NSMutableURLRequest(URL: url!, cachePolicy: cachePolicy, timeoutInterval: 2.0)
request.HTTPMethod = "POST"
// set Content-Type in HTTP header
let boundaryConstant = "----------V2ymHFg03esomerandomstuffhbqgZCaKO6jy";
let contentType = "multipart/form-data; boundary=" + boundaryConstant
NSURLProtocol.setProperty(contentType, forKey: "Content-Type", inRequest: request)
// set data
var dataString = "data=\(data)&engine=\(engine)"
let requestBodyData = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
request.HTTPBody = requestBodyData
// set content length
//NSURLProtocol.setProperty(requestBodyData.length, forKey: "Content-Length", inRequest: request)
var response: NSURLResponse? = nil
var error: NSError? = nil
let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)
if let results = NSJSONSerialization.JSONObjectWithData(reply!, options: nil, error: &error) as? [String: String]{
if let name = results["name"]{
labelTestOutput.text = name as? String
}
}
Thanks for the help
You can do it asynchronously with Alamofire library as simple as that:
typealias JSONdic = [String: AnyObject]
let param = ["data": "somedata", "engine": "someEngine"]
Alamofire.request(.POST, URLString: "xxxxx.php", parameters: param).responseJSON() {
(_,_,json,_) in
if let json = json as? JSONdic, name = json["name"] as? String {
// do something with name
}
}