В настоящее время я пытаюсь отправить массив, содержащий текст и изображения, из моего файла PHP в мое приложение iOS с помощью NSURLSession. Изначально я тестировал только текстовый массив, который я конвертировал в формат JSON перед отправкой в приложение: все работало нормально, но теперь мне нужно отправить массив с текстом и изображениями, поэтому я сделал что-то вроде этот:
Вот код:
— PHP (извините за неанглийские комментарии и имена переменных)
<?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 и (aka profileImage) и immagineUni (aka universityImage) — это два пути, извлекаемые из базы данных (например, «./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];
Проблема в этом решении заключается в том, что я не могу напечатать содержимое массива, который должен содержать содержимое массива PHP, но с помощью отладчика я вижу данные не NULL, поэтому кажется, что что-то отправлено.
Ваша строка PHP говорит:
echo $datiutente;
Вместо этого вы хотите вернуть JSON, который может быть легко проанализирован клиентом. Таким образом, вы должны указать, что ответ будет JSON (и сделать это до того, как вы echo
что-нибудь):
header('Content-type: application/json');
И тогда, эхом данных ответа будет:
echo json_encode($datiutente);
А затем проанализировать его на стороне клиента, вы хотите:
[[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];
Кстати, когда вы создаете ответ JSON, вы не можете включать двоичные данные (а именно, полезную нагрузку изображения). Поэтому, если вы собираетесь включить изображения в ответ JSON, убедитесь, что base64_encode
их (а затем декодировать их на стороне клиента):
$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
);
Лично я не склонен включать полезную нагрузку изображения в JSON (так как он увеличивает размер ответа на несколько порядков, замедляя его). Я мог бы предпочесть просто включить URL-адрес изображения в ответ и позволить клиенту запрашивать само изображение, если и когда оно ему нужно. Вы можете сделать приложение более отзывчивым с таким дизайном. Но это зависит от вас.
Обратите внимание, в дополнение к вышеупомянутым изменениям, я также добавил success
код. Это может быть полезно, чтобы клиент мог быстро определить, был ли ответ успешным или нет.
Очевидно, вы также хотите JSON кодировать сбои. Например, если соединение MySQL не удалось, вы должны указать это в ответе JSON (и включить соответствующую информацию, предоставленную MySQL):
if (!$con) {
$response = array(
"success" => false,
"message" => "Server non trovato",
"sqlerror" => mysql_error(),
"sqlerrno" => mysql_errno()
);
echo json_encode($response);
exit();
}
Как только вы получите эту работу, несколько других наблюдений:
Не просто взять опубликованные данные и использовать их в запросе. Это подвергает вас атакам SQL-инъекций. Запомни mysql_real_escape_string
этот вход, прежде чем использовать его в запросе.
Я бы, вероятно, изменил запрос, созданный клиентским кодом, на application/x-www-form-urlencoded
запрос (например, user=...
) или application/json
запрос (например, использование NSJSONSerialization dataWithJSONObject
построить запрос, который выглядит как {"user": "..."}
). а затем проанализировать его на стороне сервера.
Обратите внимание, что этот интерфейс MySQL устарел. Как говорят в документах:
Это расширение было объявлено устаревшим в PHP 5.5.0 и удалено в PHP 7.0.0. Вместо этого MySQLi или же PDO_MySQL расширение должно быть использовано. Смотрите также MySQL: выбор API руководство и связанный FAQ для дополнительной информации.
Других решений пока нет …