0

I'm currently trying to send an array, which contains text and images, from my PHP file to my iOS application using NSURLSession. Initially, I've tested with a text-only array which I've converted in JSON format before sending to my application: everything worked fine, but now I need to send an array with text and images, so I've done something like this:
Here is the code:
- PHP (sorry for non - english comments and variable names)

<?php

    // Connessione al server mediante le credenziali.
    $con = mysql_connect("localhost", "mobdev2015", "Pistacchio1");
    if(!$con){
        die("Server non trovato" . mysql_error());
    }

    // Seleziono il database.
    $db = mysql_select_db("gandalf", $con);
    if(!$db){
        die("Database non trovato" . mysql_error());
    }
    // Mi metto in ascolto per ricevere l'user dall'utente.
    $user = file_get_contents('php://input');


    // Prelevo i dati dello studente, controllando se tutto va bene.
    $sql = "SELECT * FROM Studente WHERE nomeUtente = '$user' ";

    if(!mysql_query($sql, $con))
        die ("Errore nella ricerca dello studente" . mysql_error());

    // Prelevo i valori delle colonne del result set.
    $result = mysql_query($sql, $con);
    $resultSet = mysql_fetch_row($result);

    // Prelevo il percorso dell'immagine dell'università dello studente, dato l'id nel risultato,
    // Facendo sempre i vari controlli del caso.
    $queryImmagineUni = "SELECT immagine FROM Universita WHERE id = '$result[5]'";
    if(!mysql_query($queryImmagineUni, $con))
        die ("Errore nella ricerca dell'università" . mysql_error());
    $result = mysql_query($queryImmagineUni, $con);
    $pathImmagine = mysql_result($result, 0);

    //Inserisco tutti i dati nell'array, ottenendo le immagini mediante file_get_contents.
    $datiutente = array(
        "nome" => $resultSet[1],
        "cognome" => $resultSet[2],
        "email" => $resultSet[4],
        "nomeUtente" => $resultset[6],
        "immagineProfilo" => file_get_contents($resultSet[3]),
        "immagineUni" => file_get_contents($pathImmagine)

    );

    //Mando in output il risultato e chiudo la connessione.
    echo $datiutente;
    mysql_close($con);
?>

immagineProfilo and (aka profileImage) and immagineUni (aka universityImage) are two paths retrieved from database (like "./folder/image.jpg").

  • iOS:

    // Setting up the url of the request (we will call a php file).
    NSURL *url = [[NSURL alloc]initWithString:@"http://inserturlhere.com/userdata.php"];
    
    // Creating the NSMutableRequest object, which will contain the HTML headers and the nickname needed to retrieve data.
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
    // Converting the NSString into NSData to append at MutableURLRequest.
    NSData *postData = [user dataUsingEncoding:NSASCIIStringEncoding];
    //Setting the method to post
    [request setHTTPMethod:@"POST"];
    // Setting the body of the post to the reqeust
    [request setHTTPBody:postData];
    //
    /* 
     NSURLSession needs a NSURLSessionConfiguration to run, so we instiate a NSURLSessionConfiguration object saying
     we want to use a default Session, then we create a session with that configuration
     */
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    // Starting a dataTask with the request previously defined. The completion handler will be used to manage the response
    // from the server, stored in a NSURLResponse object.
    [[session  dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    
       NSArray *datiUtente =  [NSKeyedUnarchiver unarchiveObjectWithData:data];
       NSLog(@"%@", datiUtente);
    }]resume];
    

The problem in this solution is I can't print the content of the array which should contain the contents of the PHP array, but using the debugger I can see data is not NULL, so it seems like something is sent.

1 Answer 1

1

Your PHP line says:

echo $datiutente;

Instead, you want to return JSON, which can be easily parsed by the client. So, you should specify that the response will be JSON (and do this before you echo anything):

header('Content-type: application/json');

And then, the echoing of the response data would be:

echo json_encode($datiutente);

And then to parse it on the client side, you want:

[[session  dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (error) {
        NSLog(@"%@", error);
    }
    if (!data) {
        return;
    }
    NSError *parseError;
    NSArray *datiUtente = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
    if (datiUtente) {
        NSLog(@"responseObject = %@", datiUtente);
    } else {
        NSLog(@"parseError = %@", parseError);
        NSLog(@"responseString = %@", [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding]);
    }
}] resume];

By the way, when you build a JSON response, you cannot include binary data (namely, the image payload). So if you're going to include the image(s) in the JSON response, make sure to base64_encode them (and then decode them on the client side):

$datiutente = array(
    "nome" => $resultSet[1],
    "cognome" => $resultSet[2],
    "email" => $resultSet[4],
    "nomeUtente" => $resultset[6],
    "immagineProfilo" => base64_encode(file_get_contents($resultSet[3])),
    "immagineUni" => base64_encode(file_get_contents($pathImmagine)),
    "success" => true
);

Personally, I would not be inclined to include the image payload in the JSON ar all (because it increases the size of the response by several orders of magnitude, slowing it down). I might prefer to just include a URL for the image in the response, and let the client request the image itself, if and when it needs it. You can make the app more responsive with that sort of design. But that's up to you.

Note, in addition to the above change, I also added a success code. This can be useful so that the client can quickly determine whether the response was successful or not.

Obviously, you want to JSON encode failures, too. For example, if the MySQL connection failed, you should indicate that in a JSON response (and include the appropriate information provided by MySQL):

if (!$con) {
    $response = array(
        "success" => false, 
        "message" => "Server non trovato",
        "sqlerror" => mysql_error(), 
        "sqlerrno" => mysql_errno()
    );

    echo json_encode($response);
    exit();
}

Once you get this working, a few other observations:

  1. Do not just take the posted data and use it in a query. That exposes you to SQL injection attacks. Remember to mysql_real_escape_string that input before using it in a query.

  2. I'd probably change the request created by the client code to be a application/x-www-form-urlencoded request (e.g., user=...) or a application/json request (e.g. use NSJSONSerialization dataWithJSONObject to build request that looks like {"user": "..."}). and then parse it on the server side.

  3. Note this MySQL interface is deprecated. As the docs say:

    This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.