#php #ios #json
#php #iOS #json
Вопрос:
После попытки Register
функции в этом приложении, он показывает ошибку через UIAlert
, который говорит
Ошибка
Ожидаемый тип содержимого {[«текст / json», «приложение / json», «текст / javascript» )}, получил текст / html.
Как можно исправить этот тип ошибки? После просмотра вкладки обзор в Charles Proxy он подтверждает, что Content-Type
есть text/html; charset=UTF-8
. Charles proxy также показывает username
password
ввод и, но, похоже, он не выполняется.
Это заголовок, используемый в приложении
header("Content-Type: application/json");
Что вызывает эту ошибку и как ее можно решить?
//the web location of the service
#define kAPIHost @"http://192.168.1.3:8888"
#define kAPIPath @"iReporter/"
Редактировать
Предполагается, что приложение регистрирует пользователя в базе данных mysql, используя AFNetworking
in iOS
и Json
в соответствующем php web service
lib.php (помогает подключиться к базе данных mysql)
<?
//setup db connection
$link = mysqli_connect("localhost","root","root");
mysqli_select_db($link, "iReport");
//executes a given sql query with the params and returns an array as result
function query() {
global $link;
$debug = false;
//get the sql query
$args = func_get_args();
$sql = array_shift($args);
//secure the input
for ($i=0;$i<count($args);$i ) {
$args[$i] = urldecode($args[$i]);
$args[$i] = mysqli_real_escape_string($link, $args[$i]);
}
//build the final query
$sql = vsprintf($sql, $args);
if ($debug) print $sql;
//execute and fetch the results
$result = mysqli_query($link, $sql);
if (mysqli_errno($link)==0 amp;amp; $result) {
$rows = array();
if ($result!==true)
while ($d = mysqli_fetch_assoc($result)) {
array_push($rows,$d);
}
//return json
return array('result'=>$rows);
} else {
//error
return array('error'=>'Database error');
}
}
//loads up the source image, resizes it and saves with -thumb in the file name
function thumb($srcFile, $sideInPx) {
$image = imagecreatefromjpeg($srcFile);
$width = imagesx($image);
$height = imagesy($image);
$thumb = imagecreatetruecolor($sideInPx, $sideInPx);imagecopyresized($thumb,$image,0,0,0,0,$sideInPx,$sideInPx,$width,$height);
imagejpeg($thumb, str_replace(".jpg","-thumb.jpg",$srcFile), 85);
imagedestroy($thumb);
imagedestroy($image);
}
?>
Index.php (файл, к которому подключается приложение для вызова команд php через ответ AFNetworking Json)
<?
/* iReporter complete web demo project
*
* index.php takes care to check the "command" request
* and call the proper API function to process the user request
*
*/
// this line starts the server session - that means the server will "remember" the user
// between different API calls - ie. once the user is authorized, he will stay logged in for a while
session_start();
// the require lines include the lib and api source files
require("lib.php");
require("api.php");
// this instructs the client (in this case the iPhone app)
// that the server will output JSON data
header("Content-Type: application/json");
// the iPhone app sends over what "command" of the API it wants executed
// the tutorial covers "login","register","upload", "logout" and "stream"
// so using a switch statement for this taks makes most sense
// the functions you call inside the switch are found in the api.php file
switch ($_POST['command']) {
case "login":
login($_POST['username'], $_POST['password']);
break;
case "register":
register($_POST['username'], $_POST['password']);
break;
api.php (файл index.php подключается для вызова функций сервера, используемых в приложении, таких как вход в систему и регистрация)
<?
// helper function, which outputs error messages in JSON format
// so that the iPhone app can read them
// the function just takes in a dictionary with one key "error" and
// encodes it in JSON, then prints it out and then exits the program
function errorJson($msg){
print json_encode(array('error'=>$msg));
exit();
}
// register API
function register($user, $pass) {
//check if username exists in the database (inside the "login" table)
$login = query("SELECT username FROM login WHERE username='%s' limit 1", $user);
if (count($login['result'])>0) {
//the username exists, return error to the iPhone app
errorJson('Username already exists');
}
//try to insert a new row in the "login" table with the given username and password
$result = query("INSERT INTO login(username, pass) VALUES('%s','%s')", $user, $pass);
if (!$result['error']) {
//registration is successful, try to also directly login the new user
login($user, $pass);
} else {
//for some database reason the registration is unsuccessfull
errorJson('Registration failed');
}
}
//login API
function login($user, $pass) {
// try to match a row in the "login" table for the given username and password
$result = query("SELECT IdUser, username FROM login WHERE username='%s' AND pass='%s' limit 1", $user, $pass);
if (count($result['result'])>0) {
// a row was found in the database for username/pass combination
// save a simple flag in the user session, so the server remembers that the user is authorized
$_SESSION['IdUser'] = $result['result'][0]['IdUser'];
// print out the JSON of the user data to the iPhone app; it looks like this:
// {IdUser:1, username: "Name"}
print json_encode($result);
} else {
// no matching username/password was found in the login table
errorJson('Authorization failed');
}
}
//upload API
function upload($id, $photoData, $title) {
// index.php passes as first parameter to this function $_SESSION['IdUser']
// $_SESSION['IdUser'] should contain the user id, if the user has already been authorized
// remember? you store the user id there in the login function
if (!$id) errorJson('Authorization required');
// check if there was no error during the file upload
if ($photoData['error']==0) {
// insert the details about the photo to the "photos" table
$result = query("INSERT INTO photos(IdUser,title) VALUES('%d','%s')", $id, $title);
if (!$result['error']) {
// fetch the active connection to the database (it's initialized automatically in lib.php)
global $link;
// get the last automatically generated ID in the photos table
$IdPhoto = mysqli_insert_id($link);
// move the temporarily stored file to a convenient location
// your photo is automatically saved by PHP in a temp folder
// you need to move it over yourself to your own "upload" folder
if (move_uploaded_file($photoData['tmp_name'], "upload/".$IdPhoto.".jpg")) {
// file moved, all good, generate thumbnail
thumb("upload/".$IdPhoto.".jpg", 180);
//just print out confirmation to the iPhone app
print json_encode(array('successful'=>1));
} else {
//print out an error message to the iPhone app
errorJson('Upload on server problem');
};
} else {
errorJson('Upload database problem.'.$result['error']);
}
} else {
errorJson('Upload malfunction');
}
}
//logout API
function logout() {
// by saving an empty array to $_SESSION you are
// effectively destroying all the user session data
// ie. the server won't "remember" anymore anything about
// the current user
$_SESSION = array();
// and to make double-sure, there's also a built-in function
// which wipes out the user session
session_destroy();
}
//stream API
//
// there are 2 ways to use the function:
// 1) don't pass any parameters - then the function will fetch all photos from the database
// 2) pass a photo id as a parameter - then the function will fetch the data of the requested photo
//
// Q: what "$IdPhoto=0" means? A: It's the PHP way to say "first param of the function is $IdPhoto,
// if there's no param sent to the function - initialize $IdPhoto with a default value of 0"
function stream($IdPhoto=0) {
if ($IdPhoto==0) {
// load the last 50 photos from the "photos" table, also join the "login" so that you can fetch the
// usernames of the photos' authors
$result = query("SELECT IdPhoto, title, l.IdUser, username FROM photos p JOIN login l ON (l.IdUser = p.IdUser) ORDER BY IdPhoto DESC LIMIT 50");
} else {
//do the same as above, but just for the photo with the given id
$result = query("SELECT IdPhoto, title, l.IdUser, username FROM photos p JOIN login l ON (l.IdUser = p.IdUser) WHERE p.IdPhoto='%d' LIMIT 1", $IdPhoto);
}
if (!$result['error']) {
// if no error occured, print out the JSON data of the
// fetched photo data
print json_encode($result);
} else {
//there was an error, print out to the iPhone app
errorJson('Photo stream is broken');
}
}
?>
Редактировать: ошибка отображается при попытке зарегистрировать функцию на экране входа в приложения
Комментарии:
1. Пожалуйста, добавьте весь соответствующий код в сам вопрос, а не в виде ссылок за пределами сайта. Вы также должны более подробно объяснить, что делает ваш код. Когда вы получаете это сообщение? В PHP? Когда ваше приложение отправляет ответ или когда оно делает запрос? На данный момент это очень неясно.
2. Из-за ошибки кажется, что сервер не возвращает ответ json, как ожидало приложение. Проверьте код api и убедитесь, что ваш api возвращает ответ json в сценариях успеха и ошибок
3. Я не эксперт в php, но я думаю, что вы должны использовать
echo json_encode($result);
илиecho errorJson()
в соответствующих случаях.4. Вы должны использовать параметризованные подготовленные операторы вместо того, чтобы вручную экранировать и строить свои запросы подобным образом.
5.Никогда не храните пароли в виде открытого текста! Предупреждение: храните только хэши паролей. Используйте PHP
password_hash()
иpassword_verify()
. Если вы используете версию PHP ниже 5.5 (на что я очень надеюсь, что это не так), вы можете использовать библиотеку password_compat, чтобы получить ту же функциональность.