i have recently wanted to use Afnetworking in my ios application. the same page responds me by using ASIHTTPREQUEST. but it simply does not with the AFNetworking. Here is my effort.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"user[height]": #"10",
#"user[weight]": #"255"};
[manager POST:#"http://localhost:8888/TestingPost/post.php" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Now i have tried many options like adding serialization to different xml / json / html. but of no use.
On PHP page i am not doing something fancy just printing out whatever is posted on the page. still here it is.
<?php
// Show all information, defaults to INFO_ALL
header('Content-type: application/JSON');
print_r($_POST[]);
/*
$first_name = $_POST["first_name"];
$last_name = $_POST["last_name"];
$password = $_POST['password'];
*/
//echo( "hurray");
?>
Can you please shed some light on it. i want to switch from ASIhttprequest to newest and more supported.
Here is the result for the request
Networking_example[1777:41979] Error: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: internal server error (500)" UserInfo=0x7f9feae16d60 {com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7f9fedb029a0> { URL: http://localhost:8888/TestingPost/post.php } { status code: 500, headers {
Connection = close;
"Content-Length" = 0;
"Content-Type" = "text/html";
Date = "Thu, 16 Oct 2014 18:08:08 GMT";
Server = Apache;
"X-Powered-By" = "PHP/5.5.10";
} }, NSErrorFailingURLKey=http://localhost:8888/TestingPost/post.php, com.alamofire.serialization.response.error.data=<>, NSLocalizedDescription=Request failed: internal server error (500)}
If your PHP is using $_POST, that means that you are ok using the default requestSerializer of AFHTTPRequestSerializer (i.e. an application/x-www-form-urlencoded request).
But your JSON is not generation JSON response, so you have to change the responseSerializer to AFHTTPResponseSerializer.
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
And your PHP page is reporting a 500 error. That is an "Internal Server Error", for which the status code definition says:
The server encountered an unexpected condition which prevented it from fulfilling the request.
That suggests a PHP error. Perhaps you intended:
print_r($_POST);
Generally, when interacting with web service, it's better to generate JSON response, e.g.
echo(json_encode($_POST));
Obviously, if you generate JSON response, you might also want to use the default [AFJSONResponseSerializer serializer] setting, rather than changing it to AFHTTPResponseSerializer.
Related
I'm trying to learn AFNetworking, and I've taken a sample from their Github. I don't know what parameters to set in dataToPostusing the the php I have. I'm new to Objective-C and php. Can someone take a look at my snippet and my php to see what I'm missing. It's hard to find "upload" tutorials for AFNetworking, but there are TONS of JSON tutorials out there.
I want to use a NSMutableURLRequest because eventually I would like to upload from an array or UITableview; here is mt code so far:
PHP:
<?php
header("Content-Type: application/json");
$uploaddir = './'; //Uploading to same directory as PHP file
$file = basename($_FILES['userfile']['name']);
$uploadFile = $file;
$randomNumber = rand(0, 99999);
$newName = $uploadDir . $randomNumber . $uploadFile;
if (!is_uploaded_file($_FILES['userfile']['tmp_name'])) {
$result = array("success" => false);
echo json_encode($result);
exit();
}
if ($_FILES['userfile']['size']> 300000) {
$result = array("success" => false, "message" =>"the uploaded file is too big");
echo json_encode($result);
exit();
}
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $newName)) {
$postsize = ini_get('post_max_size'); //Not necessary, I was using these
$canupload = ini_get('file_uploads'); //server variables to see what was
$tempdir = ini_get('upload_tmp_dir'); //going wrong.
$maxsize = ini_get('upload_max_filesize');
//echo "http://localhost:8888/upload/{$file}" . "\r\n" . $_FILES['userfile']['size'] . "\r\n" . $_FILES['userfile']['type'] ;
$result = array("success" => true,
"code" => 0,
"message" => "success",
"postsize" => $postsize,
"canupload" => $canupload,
"tempdir" => $tempdir,
"maxsize" => $maxsize);
echo json_encode($result);
}
?>
Xcode:
// 1. Create AFHTTPRequestSerializer which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
// 2. Create an NSMutableURLRequest.
NSMutableURLRequest *request =
[serializer multipartFormRequestWithMethod:#"POST" URLString:#"http://my.com/upload/upload.php"
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData
name:#"userfile"
fileName:#"myimage.jpg"
mimeType:#"image/jpeg"];
}];
// 3. Create and use AFHTTPRequestOperationManager to create an AFHTTPRequestOperation from the NSMutableURLRequest that we just created.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation =
[manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure %#", error.description);
}];
// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
NSInteger totalBytesWritten,
NSInteger totalBytesExpectedToWrite) {
NSLog(#"Wrote %ld/%ld", (long)totalBytesWritten, (long)totalBytesExpectedToWrite);
}];
// 5. Begin!
[operation start];
ERROR (resolved):
2014-03-31 15:37:46.921 TestingUpload[7190:60b] Wrote 32768/59063
2014-03-31 15:37:46.922 TestingUpload[7190:60b] Wrote 59063/59063
2014-03-31 15:37:46.923 TestingUpload[7190:60b] Wrote 32768/59063
2014-03-31 15:37:46.923 TestingUpload[7190:60b] Wrote 59063/59063
2014-03-31 15:37:46.925 TestingUpload[7190:60b] Success {
canupload = 1;
code = 0;
maxsize = 32M;
message = success;
postsize = 32M;
success = 1;
tempdir = "/Applications/MAMP/tmp/php";
}
2014-03-31 15:37:46.927 TestingUpload[7190:60b] Success {
canupload = 1;
code = 0;
maxsize = 32M;
message = success;
postsize = 32M;
success = 1;
tempdir = "/Applications/MAMP/tmp/php";
}
Thanks for any help and explanation. Thank you!
Your PHP is looking for the field name userfile, but your Objective-C is using attachment. You must use the same field name on both platforms. I also assume the "<$php" was just a typo and that you intended "<?php".
A couple of other improvements you might want to consider:
I would suggest that you might want to change your PHP to return JSON rather than just writing text strings. It will be easier for your Objective-C code to parse the responses and differentiate between various errors and success.
For example, your if successful, your PHP might do the following:
$result = array("success" => true, "code" => 0, "message" => "success");
Or if you wanted to log those additional values, as in your existing code sample, you could:
$result = array("success" => true,
"code" => 0,
"message" => "success",
"postsize" => $postsize,
"canupload" => $canupload,
"tempdir" => $tempdir,
"maxsize" => $maxsize);
If unsuccessful, you might do:
$result = array("success" => false, "code" => 1, "message" => "file not found");
or
$result = array("success" => false, "code" => 2, "message" => "file too large");
Regardless of which $result is chosen, when done, you should JSON encode it and echo it (rather than echoing the simple text string):
echo json_encode($result);
Clearly, use whatever codes and messages you want, but the idea is to return JSON, which can be easily parsed to determine if the upload request was successful, and if not, then why. Trying to parse simple text responses from the server will be inherently fragile.
Anyway, your Objective-C can then parse this response and just check the success or code values and handle these scenarios appropriately.
I would not suggest having the PHP save the uploads in the same folder as the PHP, itself. At the very least, I'd create a dedicated subdirectory for the uploads. I'd personally choose a directory completely outside the web server's directory structure.
On the basis of your updated code sample and reported warnings/errors, I have a few observations:
You are receiving the message about multipartFormRequestWithMethod being deprecated because you're using the rendition without the error parameter, but that's been replaced with another rendition with this additional parameter. See the declaration of this method in AFURLRequestSerialization.h for more information.
Your error about the text/html is a result of the fact that PHP is sending a response with a header that reports a Content-type of text/html. If your PHP script is not sending JSON back in your PHP, you have to change your your Objective-C code so it knows to expect an HTTP response (by default, it expects JSON back):
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
That tells the AFHTTPRequestOperationManager to accept any HTTP response back from the server.
Alternatively, if you change your PHP to return JSON (and you should, IMHO), you need to not only change the PHP code to echo the json_encode of the results, but also inform PHP to specify the appropriate Content-Type in the header. So before you echo any JSON in your PHP), add the following line to the PHP code:
header("Content-Type: application/json");
You said:
I thought the content type was defined in mimetype
The mimetype defines the Content-type for that part of the multipart request. But the whole request has its own Content-type header, too. The response also bears a Content-type setting in its header. This error, is telling you that the response bore a Content-type of text/html, and it expected application/json. (See my prior point regarding fixing that.)
I have a table managed by FOSUserBundle with users in it in a Symfony2 application. I am able to access routes protected by a firewall with cURL without any problems. Let's say I have a route /api/something that is protected and I wanted to access it with cURL, I used:
curl -v -u paul http://example/web/app_dev.php/api/something/
The above works no problem. However, from my app, it always returned a 401: You are not authenticatedd when I use the following snippet below. I converted it to base 64 since AFNetworking says it has to be in that format. What am I missing??
NSData *pass = [#"somestring" dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64pass = [pass base64EncodedStringWithOptions:0];
NSData *user = [#"anotherstring" dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64user = [user1 base64EncodedStringWithOptions:0];
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:#"Accept" value:#"application/json"];
[self setAuthorizationHeaderWithUsername:base64user password:base64pass];
Here is the HTTP Header returned and AFNetworking is not setting the headers. How can I accomplish this task?
{ status code: 401, headers {
Allow = "GET, POST";
"Cache-Control" = "no-cache";
Connection = "Keep-Alive";
"Content-Type" = "application/json";
Date = "Fri, 31 Jan 2014 14:25:48 GMT";
"Keep-Alive" = "timeout=5, max=100";
Server = "Apache/2.2.22 (Ubuntu)";
"Transfer-Encoding" = Identity;
"X-Debug-Token" = c562ea;
"X-Powered-By" = "PHP/5.3.10-1ubuntu3.9";
}
I don't know how you'll set this on your code. Here is the catch. Since you have empty password, so make the base64 of paul: like this way(remember the colon).
BASE_64 = base64 of "paul:"
Then set this http header.
Authorization: Basic BASE_64
Of course remove this one as your requesting the authorization through headers.
[self setAuthorizationHeaderWithUsername:base64user password:base64pass];
I'm trying to visit the php page from my server, but no return. The code below should be fine, because when I change my site address (site1111111) to another one (site222222), the code works. The site2 uses JSON.aspx, which I don't know the code, but returns:
{aaaa:false}
Edit and Add: Not sure if it matters, when I say site1111111, it's actually site222222/subfolder/. End edit.
My PHP code is simple test, just populate the same json string:
<html><body>
$arr = array ('aaaa'=>false);
echo json_encode($arr);
</body></html>
The iOS app code is here:
NSString *urlString = #"http://site111111111111111111/welcome.php";
//urlString = #"http://site222222222222/JSON.aspx?function=ffff&item=aaaa";
NSURL *url = [NSURL URLWithString:urlString];
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
NSLog(#"%#", data);
//<7b226973 64696769 74616c22 3a66616c 73657d> //print data from site2222222
//<3c68746d 6c3e0d0a 3c626f64 793e0d0a 0d0a3c21 2d2d5765 6c636f6d 65203c62 723e0d0a 596f7572 20656d61 696c2061 64647265 73732069 733a200d 0a2d2d3e 0d0a0d0a 7b226973 64696769 74616c22 3a66616c 73657d0d 0a3c2f62 6f64793e 0d0a3c2f 68746d6c 3e0d0a> //data from site11111
if (error)
{
NSLog(#"error==%#==",[error localizedDescription]);
}
else
{
NSLog(#"no error for request"); //both site1111 and site2222 print this out
NSError *errorInJsonParsing;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&errorInJsonParsing];
if(errorInJsonParsing)
{
NSLog(#"error in json==%#==",[error localizedDescription]);
}
else
{
if ([[json valueForKey:#"aaaa"] boolValue] ) {
NSLog(#"YES");
} else {
NSLog(#"NO");
}
}
}
When running the code, I got null json, printed from if condition if(errorInJsonParsing).
I don't know if I miss anything that connects my php and ios request. Please help. TIA!
site1111 is not returning json, it's returning html. if you decode those hex bytes you'll see this:
<html>
<body>
<!--Welcome <br>
Your email address is:
-->
{"isdigital":false}
</body>
</html>
Fix the site so it returns json and you should be good to go.
I am a beginner to iOS. I have a simple web service that retrieves data from a table and sends out the results in JSON. I am trying to communicate with that web service from iOS to receive the JSON response but facing issues. This is the error i receive:
Request Failed with Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Expected content type {(
"text/json",
"application/json",
"text/javascript"
)}, got text/html" UserInfo=0x7598e70
Here are my code snippets:
PHP Web Service:
$stmt = "SELECT STORE_TYPE, STORE_NAME FROM STORE WHERE STORE_ZIP = $zip";
$result = mysqli_query($this->databaseconnection, $stmt);
$storelist = array();
$store = array();
$jsondata;
while ($row = mysqli_fetch_assoc($result)) {
$store['STORE_TYPE'] = $row['STORE_TYPE'];
$store['STORE_NAME'] = $row['STORE_NAME'];
array_push($storelist,$store);
}
$jsondata = json_encode($storelist);
echo $jsondata;
I am getting the following result when i execute my php form the browser:
[{"STORE_TYPE":"GROCERY","STORE_NAME":"Walmart"},{"STORE_TYPE":"BAKERY","STORE_NAME":"Lanes Bakery"},{"STORE_TYPE":"GROCERY","STORE_NAME":"Copps"}]
iOS Code Snippet to communicate with the Web Service:
NSURL *url = [NSURL URLWithString:#"http://localhost/~Sandeep/store/store.php?rquest=getstores&zip=53715"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
I looked at a lot of tutorials and they all say that performing a 'json_encode' on an array in php encodes the data in JSON format and 'echo' of that is the way to go send the encoded JSON as a response. For some reason my iOS is not seeing that as JSON. I am not sure what I am missing/doing wrong here.
I really appreciate your inputs on this.
Thanks!
You need to set the correct content type(use header), the error lists the acceptable types though you should use application/json
$stmt = "SELECT STORE_TYPE, STORE_NAME FROM STORE WHERE STORE_ZIP = $zip";
$result = mysqli_query($this->databaseconnection, $stmt);
$storelist = array();
$store = array();
$jsondata;
while ($row = mysqli_fetch_assoc($result)) {
$store['STORE_TYPE'] = $row['STORE_TYPE'];
$store['STORE_NAME'] = $row['STORE_NAME'];
array_push($storelist,$store);
}
$jsondata = json_encode($storelist);
header('Content-Type: application/json');
echo $jsondata;
Now I'm trying to POST jpeg files to MySQL via PHP and GET from MySQL to iOS.
In GET method I encode jpeg(as NSData) and some related data(ex. caption, timestamp) to JSON on PHP script using json_encode().
{"caption":"(captiondata)","img":"(imagedata)","timestamp":"(timestampdata)"}
Then I set the datas into array like,
[{"caption":"(captiondata)","img":"(imagedata)","timestamp":"(timestampdata)"},
{"caption":"(captiondata)","img":"(imagedata)","timestamp":"(timestampdata)"},
.......,
{"caption":"(captiondata)","img":"(imagedata)","timestamp":"(timestampdata)"}]
I believe I can parse and get this JSON by echo (json_encode ()) on PHP and SBJsonParser on iOS but nothing returns to my App. Here's my code in iOS.(Also I use TTURLRequest by Three20)
TTURLRequest* request = [TTURLRequest requestWithURL:url delegate:self];
request.cachePolicy = cachePolicy;
TTURLJSONResponse* response = [[[TTURLJSONResponse alloc] init] autorelease];
request.response = response;
[request send];
- (void)requestDidFinishLoad:(TTURLRequest*)request {
TTURLJSONResponse* response = request.response;
NSLog(#"%#",response);
}
Can you print all the logs in requestDidFinishLoad:?
The response is the rootObject of TTURLJSONResponse.
- (void)requestDidFinishLoad:(TTURLRequest*)request {
TTURLJSONResponse *response = request.response;
NSDictionary *dict = response.rootObject;
NSLog(#"dict : %#",dict);
}
In your case,
- (void)requestDidFinishLoad:(TTURLRequest*)request {
TTURLJSONResponse* response = request.response;
NSLog(#"%#",response);
}
The response may look like <TTURLJSONResponse: 0x125398c0>
If still nothing returns, you may check the requestDidFinishLoad: is been called and not the cache issue.