0

I want to POST Data in a Textfield via HTTPS to a Webserver using Swift and PHP and tried this Example POST data to a PHP method from Swift, but it is not compatible with PHP7.

Now this is for PHP7 and Swift 4 but i got an empty entry in the MySql Database.

I think thats the PHP-File...

Use Xcode 10.1 Any Solution?

Swift:

import UIKit

class MessageViewController: UIViewController {
    @IBOutlet weak var nachricht: UITextField!

    @IBAction func submit(_ sender: Any) {
        let url = NSURL(string: "http://localhost.com") // localhost MAMP - change to point to your database server

        var request = URLRequest(url: url! as URL)
        request.httpMethod = "POST"

        var dataString = "secretWord=???" // starting POST string with a secretWord

        // the POST string has entries separated by &
        dataString = dataString + "&nachricht=\(nachricht.text!)" // add items as name and value

        // convert the post string to utf8 format
        let dataD = dataString.data(using: .utf8) // convert to utf8 string

        do {
            // the upload task, uploadJob, is defined here
            let uploadJob = URLSession.shared.uploadTask(with: request, from: dataD) { data, response, error in
                if error != nil {
                    // display an alert if there is an error inside the DispatchQueue.main.async
                    DispatchQueue.main.async {
                        let alert = UIAlertController(title: "Upload Didn't Work?", message: "Looks like the connection to the server didn't work.  Do you have Internet access?", preferredStyle: .alert)
                        alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
                        self.present(alert, animated: true, completion: nil)
                    }
                } else {
                    if let unwrappedData = data {
                        let returnedData = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue) // Response from web server hosting the database

                        if returnedData == "1" { // insert into database worked
                            // display an alert if no error and database insert worked (return = 1) inside the DispatchQueue.main.async
                            DispatchQueue.main.async {
                                let alert = UIAlertController(title: "Upload OK?", message: "Looks like the upload and insert into the database worked.", preferredStyle: .alert)
                                alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
                                self.present(alert, animated: true, completion: nil)
                            }
                        } else {
                            // display an alert if an error and database insert didn't worked (return != 1) inside the DispatchQueue.main.async
                            DispatchQueue.main.async {
                                let alert = UIAlertController(title: "Upload Didn't Work", message: "Looks like the insert into the database did not worked.", preferredStyle: .alert)
                                alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
                                self.present(alert, animated: true, completion: nil)
                            }
                        }
                    }
                }
            }
            uploadJob.resume()
        }
    }
}

PHP File:

<?php
$secret = $_POST["secretWord"];
if ("???" != $secret) exit; // note the same secret as the app - could be let out if this check is not required. secretWord is not entered by the user and is used to prevent unauthorized access to the database

$nachricht = $_POST['nachricht'];


// POST items should be checked for bad information before being added to the database.

// Create connection
$mysqli=mysqli_connect("localhost","db","db_pass","db_usr"); // localhost, user name, user password, database name

// Check connection
if (mysqli_connect_errno())
{
    echo "
    Failed to connect to MySQL: " . mysqli_connect_error();
}

$query = "insert into `db` (nachricht) value ('".$nachricht."')";
$result = mysqli_query($mysqli,$query);

echo $result; // sends 1 if insert worked
?>
Humfeld
  • 61
  • 1
  • 1
  • 5
  • The PHP version on your server should be entirely irrelevant to your problem. What's the exact problem you are having? – Andy Ibanez Nov 28 '18 at 20:24
  • The Problem is, that i got an empty entry in the Database. The written Text in the Swift Textfield will not be transmitted to the Database. – Humfeld Nov 29 '18 at 08:07
  • I can't understand the "$query" part. What are you trying to do exactly? – Melroy Fernandes Dec 03 '18 at 07:16
  • Oh, sorry. I have updated the code. I want to pass the text (nachricht) from the app, via the php file of a database – Humfeld Dec 04 '18 at 12:03

3 Answers3

1

I do not have much info on the PHP part of your problem. But i would recommend you try using "https://github.com/Alamofire/Alamofire" for all your networking needs as it supports Swift 4 with PHP7. It also reduces the number of lines of code you need to write.

So with Alamofire your POST request would look something like this.

import UIKit
import Alamofire

class MessageViewController: UIViewController {
@IBOutlet weak var nachricht: UITextField!

@IBAction func submit(_ sender: Any) {
    let body: Parameters = [
        "secretWord":"???",
        "nachricht":"\(nachricht.text!)",
    ]

    Alamofire.request("http://localhost.com", method: .post, parameters: body, encoding: JSONEncoding.default).responseJSON { response in

        print("Your response from server is: \(response)")

    }
  }
}

Hope this solves the Swift part of your problem.

EDIT: As requested here is an update. I have implemented your request without using a networking manager (Alamofire)

import UIKit

class MessageViewController: UIViewController {
@IBOutlet weak var nachricht: UITextField!

@IBAction func submit(_ sender: Any) {
    // MARK: Preparing json data
    let parameters: [String: Any] = [
        "secretWord":"???",
        "nachricht":"\(nachricht.text!)",
    ]

    //Serialise Parameters to JSON data.
    let jsonData = try? JSONSerialization.data(withJSONObject: parameters)

    // create post request
    let url = URL(string: "http://localhost.com")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"

    // insert json data to the request
    request.httpBody = jsonData

    let task = URLSession.shared.dataTask(with: request) { data, response, error in

        print("Session Response: \(String(describing: response!))")

        let httpResponse = response as? HTTPURLResponse
        let statusCode = httpResponse?.statusCode
        if statusCode == 404 {
            DispatchQueue.main.async {
                // create the alert
                let alert = UIAlertController(title: "Server not available", message: "Try again later.", preferredStyle: UIAlertController.Style.alert)

                // add an action (button)
                alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))

                // show the alert
                self.present(alert, animated: true, completion: nil)
            }
        }else{

            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }

            let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
            if let responseJSON = responseJSON as? [String: Any] {

                print("Your response from server is: \(responseJSON)")
            }
        }
    }
    task.resume()
}
}
Cedan Misquith
  • 1,134
  • 9
  • 20
  • Thanks for the help, but I would like to have my own script, server and so one. I've used firebase before. – Humfeld Nov 29 '18 at 08:10
  • @Humfeld I have edited my answer and implemented your request without using any networking manager. Please check. – Cedan Misquith Nov 29 '18 at 16:34
  • You are nice, but it did not work. The code works without problems. Still no entry in the Database. This is from Xcode: – Humfeld Dec 02 '18 at 10:08
  • @Humfeld According to the Session Response you seem to be getting a 200 Status Code. Which means the API call was successful but it did not send any response. So your swift code is perfectly fine. You need to look in to the backend part of you code. The PHP code is not accepting the `POST` data. – Cedan Misquith Dec 03 '18 at 04:31
  • Hmm, So the bug is in the php file? Is there another solution – Humfeld Dec 04 '18 at 11:04
  • @Humfeld Nothing from my side as i do not have much experience in PHP but i can tell you that your PHP code does not do what its supposed to do. It should be written to accept the data sent from the app and then insert it into the DB. Please check on that. – Cedan Misquith Dec 04 '18 at 17:02
0

This is from Xcode: [MC] Reading from private effective user settings. Session Response: { URL: https://localhost.com/api.php } { Status Code: 200, Headers { Connection = ( "Keep-Alive" ); "Content-Encoding" = ( gzip ); "Content-Length" = ( 21 ); "Content-Type" = ( "text/html; charset=UTF-8" ); Date = ( "Sun, 02 Dec 2018 10:06:45 GMT" ); "Keep-Alive" = ( "timeout=5, max=100" ); Server = ( Apache ); "Strict-Transport-Security" = ( "max-age=31556926" ); Vary = ( "Accept-Encoding" ); } } 2018-12-02 11:10:36.854962+0100 Localhost[2289:36190] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C1.1:2][0x7f8f76f215b0] get output frames failed, state 8196

There is no entry from the Text field transmitted in the MySql Database.

Humfeld
  • 61
  • 1
  • 1
  • 5
0

I had the same problem. My solution was to use import MultipartForm and define the form.

let form = MultipartForm(parts: [
        MultipartForm.Part(name: "id", value: incidente!.id),
        MultipartForm.Part(name: "mensaje", value: txtDescripcion.text!),
        MultipartForm.Part(name: "direccion", value: txtDireccion.text!),
        MultipartForm.Part(name: "nombre", value: txtNombre.text!),
        MultipartForm.Part(name: "telefono", value: txtTelefono.text!),
        MultipartForm.Part(name: "email", value: txtEmail.text!),
        MultipartForm.Part(name: "latitud", value: StrLatitud),
        MultipartForm.Part(name: "longitud", value: StrLongitud),
        MultipartForm.Part(name: "token", value: "44fdcv8jf3"),
        MultipartForm.Part(name: "imagen64", value: mImagenStr)
    ])

Then save the image with

file_put_contents($ruta,base64_decode($_POST['imagen64']));