Parse Json using ASIHttpRequest - iphone

I'm trying to parse JSON Using ASIHttpRequset
I wrote this code
-(void) tryASIHttpRequest{
NSString *phpUrl = #"http://www.myURL.com/subfolder/myFile.php";
NSString *dbName = #"dbName";
NSString *localHost = #"localhost";
NSString *dbUser = #"dbUser";
NSString *dbPwd = #"password";
NSString *S_user_id = [NSString stringWithFormat:#"%d",u_id0];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURL *link = [NSURL URLWithString:[phpUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:link];
[request setRequestMethod:#"POST"];
[request setPostValue:dbName forKey:#"dbName"];
[request setPostValue:localHost forKey:#"localHost"];
[request setPostValue:dbUser forKey:#"dbUser"];
[request setPostValue:dbPwd forKey:#"dbPwd"];
[request setPostValue:S_user_id forKey:#"user_id"];
[request setPostValue:#"" forKey:#"submit"];
[request setTimeOutSeconds:120];
[request setDelegate:self];
NSError *error = [request error];
[request startAsynchronous];
if (!error) {
NSData *response = [request responseData];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSArray *statuses = [parser objectWithString:json_string error:nil];
for (NSDictionary *status in statuses)
{
NSString *bo_id2 = [status objectForKey:#"bo_id"];
NSString *bo_name2 = [status objectForKey:#"bo_name"];
NSLog(#"from server using ASIHttpRequest");
NSLog(#"bo_id: %# - bo_name: %#", bo_id2, bo_name2);
}
}else{
NSLog(#"ASIHttp Error: %#", error);
}
}
and in bookOwn.php I wrote the following
<?php
if (isset($_POST['submit'])) {
$dbName = $_POST['dbName'];
$localHost = $_POST['localHost'];
$dbUser = $_POST['dbUser'];
$dbPwd = $_POST['dbPwd'];
$user_id = $_POST['user_id'];
$con = mysql_connect($localHost,$dbUser,$dbPwd);
$db_found = mysql_select_db("iktab_book");
mysql_query('SET CHARACTER SET UTF8');
mysql_query("SET NAMES utf8; ");
$check = mysql_query("SELECT * FROM d_book where bo_id IN (Select Distinct(sal_bo_id) From d_sales Where sal_user_id =" . $user_id . ")");
while($row=mysql_fetch_assoc($check))
$output[]=$row;
$json_encode =json_encode($output);
$utf8_decode = utf8_decode($json_encode);
echo $json_encode;
mb_convert_encoding($json_encode, 'UTF-8');
$html_entity_decode = html_entity_decode($json_encode);
mysql_close();
}
?>
if the code is ok, this line will be printed
from server using ASIHttpRequest
but it doesn't print and I can't determine what is the wrong in my code.
Any help ?
Thanks in Advance.

It looks like you are doing an asynchronous request [request startAsynchronous]; and then are checking on the next line to see if there is data. Asynchronous means that it will be executed later on. Usually one would become the request's delegate to get notified when the request was finished loading.
More Pressing:
Don't use ASIHTTPRequest. It has been deprecated by its author. Note the banner on the website advising using something else
For alternative URL frameworks AFnetworking is popular.
Also NSURLConnection isn't that bad.
And finally if you are targeting iOS 5 or higher (and theres not much reason to support less) you no longer need SBJSON. NSJSONSerialisation is provided by the OS for converting JSON into objects and back again.

Related

Uploading a file with ASIFormDataRequest does not work

I am using the ASIHTTPRequest framework trying to upload a file to my websever via iPhone.
Below is the code. As long as I don't use the setFile method, I get a 200 back from the server, so everthing is fine. As soon as I implement setFile, the server returns 0. I would expect a 401 or anything like this, as I could imagine that I deal with an authentication issue.
My server is an IIS, why I use the NTLM way in the request. Do I miss something?
NSInteger httpStatus;
NSString *httpResponseString;
NSError *httpRequestError;
NSArray *paths = [[[NSArray alloc] init] autorelease];
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filename = [documentsDirectory stringByAppendingPathComponent:#"abiliator_basis_de_ar.xml"];
NSURL *myURL = [NSURL URLWithString: #"http://my.url.com/"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:myURL];
[request setShouldPresentCredentialsBeforeChallenge:NO];
[request setUsername:#"myUserName"];
[request setPassword:#"myPassword"];
[request setDomain:#"myDomainName"];
[request setFile:[NSURL URLWithString:filename] forKey:#"xml"];
[request startSynchronous];
httpRequestError = [request error];
httpResponseString = [request responseString];
httpStatus = [request responseStatusCode];
if (!httpRequestError) {
httpStatus = [request responseStatusCode];
NSLog(#"Class %#, Method: %# - OK login and filetransfer successful '%i'", self.myClassName, NSStringFromSelector(_cmd), httpStatus);
}
else {
NSLog(#"Class %#, Method: %# - Error '%i' occurred sending the http request", self.myClassName, NSStringFromSelector(_cmd), httpStatus);
}
Yes the file exists, here the result from the ls:
rene-stegs-macbook-pro:~ renesteg$ ls -ltr '/Users/renesteg/Library/Application Support/iPhone Simulator/5.1/Applications/417BD791-64BC-48D0-B519-F10C7F617E36/Documents/abiliator_basis_de_ar.xml'
-rw-r--r--# 1 renesteg staff 1062 22 Mai 13:44 /Users/renesteg/Library/Application Support/iPhone Simulator/5.1/Applications/417BD791-64BC-48D0-B519-F10C7F617E36/Documents/abiliator_basis_de_ar.xml
And here the value of filename:
Filename string is: '/Users/renesteg/Library/Application Support/iPhone Simulator/5.1/Applications/417BD791-64BC-48D0-B519-F10C7F617E36/Documents/abiliator_basis_de_ar.xml
You are doing something wrong while uploading file.
it need to like this
NSFileManager *fileManager = [NSFileManager defaultManager];
request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setRequestMethod:#"POST"];
[request setTimeOutSeconds:120];
[request setPostFormat:ASIMultipartFormDataPostFormat];
[request addRequestHeader:#"Content-Type" value:#"multipart/form-data"];
if ([fileManager fileExistsAtPath:filePath] == YES) {
[request setFile:filePath withFileName:#"test.xml" andContentType:#"xml" forKey:#"FieldName"];
}
Here file path need to set for fromdata request.
Hope this will work for you.
You should probably try usingsetData:forKey: and send the data of the xml file, example below..
.....
NSURL *myURL = [NSURL URLWithString: #"http://my.url.com/"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:myURL];
[request setShouldPresentCredentialsBeforeChallenge:NO];
[request setUsername:#"myUserName"];
[request setPassword:#"myPassword"];
[request setDomain:#"myDomainName"];
[request setData:[NSData dataWithContentsOfFile:fileName] forKey:#"xml"];
[request startSynchronous];
.....
Also, you should probably make this an asynchronous request.
i think the error occurs because you should use:
[request setFile:[NSURL fileURLWithPath:filename] forKey:#"xml"];
Ok, the issue was between the line of Neels comment: missing PHP.
And this of course needs to be called in the URL, so the correct way to build the URL is:
NSURL *myURL = [NSURL URLWithString: #"http://my.url.com/upload.php"];
This way I got the mapping my iPhone httpRequest code and the PHP.
Here's the required PHP code:
<?php
$target = "upload/";
$target = $target . basename( $_FILES['xml']['name']) ;
$ok=1;
if(move_uploaded_file($_FILES['xml']['tmp_name'], $target))
{
echo "The file ". basename( $_FILES['xml']['name']). " has been uploaded";
}
else {
echo "Error uploading". basename( $_FILES['xml']['name']). " occured";
}
?>

How to upload data from iphone app to mysql data base

I have a EMR app and i want that i may send the data which i have collected like images and voice to server. in data base so how can i do this . Is there any way to send these data to server through post method.
Here is an example of a HTTP Post request
// define your form fields here:
NSString *content = #"field1=42&field2=Hello";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.example.com/form.php"]];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[content dataUsingEncoding:NSISOLatin1StringEncoding]];
// generates an autoreleased NSURLConnection
[NSURLConnection connectionWithRequest:request delegate:self];
Might want to reference http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSURLConnection_Class/Reference/Reference.html
This tutorial is also helpful http://www.raywenderlich.com/2965/how-to-write-an-ios-app-that-uses-a-web-service
In that case, you can do follow two ways:
1. if you strictly like to using POST (i like), u can using cocoahttpserver project:
https://github.com/robbiehanson/CocoaHTTPServer
In iphone app, you can do this code to send POST request:
-(NSDictionary *) getJSONAnswerForFunctionVersionTwo:(NSString *)function
withJSONRequest:(NSMutableDictionary *)request;
{
[self updateUIwithMessage:#"server download is started" withObjectID:nil withLatestMessage:NO error:NO];
NSDictionary *finalResultAlloc = [[NSMutableDictionary alloc] init];
#autoreleasepool {
NSError *error = nil;
NSString *jsonStringForReturn = [request JSONStringWithOptions:JKSerializeOptionNone serializeUnsupportedClassesUsingBlock:nil error:&error];
if (error) NSLog(#"CLIENT CONTROLLER: json decoding error:%# in function:%#",[error localizedDescription],function);
NSData *bodyData = [jsonStringForReturn dataUsingEncoding:NSUTF8StringEncoding];
NSData *dataForBody = [[[NSData alloc] initWithData:bodyData] autorelease];
//NSLog(#"CLIENT CONTROLLER: string lenght is:%# bytes",[NSNumber numberWithUnsignedInteger:[dataForBody length]]);
NSString *functionString = [NSString stringWithFormat:#"/%#",function];
NSURL *urlForRequest = [NSURL URLWithString:functionString relativeToURL:mainServer];
NSMutableURLRequest *requestToServer = [NSMutableURLRequest requestWithURL:urlForRequest];
[requestToServer setHTTPMethod:#"POST"];
[requestToServer setHTTPBody:dataForBody];
[requestToServer setTimeoutInterval:600];
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[urlForRequest host]];
NSData *receivedResult = [NSURLConnection sendSynchronousRequest:requestToServer returningResponse:nil error:&error];
if (error) {
NSLog(#"CLIENT CONTROLLER: getJSON answer error download:%#",[error localizedDescription]);
[self updateUIwithMessage:[error localizedDescription] withObjectID:nil withLatestMessage:YES error:NO];
[finalResultAlloc release];
return nil;
}
NSString *answer = [[NSString alloc] initWithData:receivedResult encoding:NSUTF8StringEncoding];
JSONDecoder *jkitDecoder = [JSONDecoder decoder];
NSDictionary *finalResult = [jkitDecoder objectWithUTF8String:(const unsigned char *)[answer UTF8String] length:[answer length] error:&error];
[finalResultAlloc setValuesForKeysWithDictionary:finalResult];
[answer release];
[self updateUIwithMessage:#"server download is finished" withObjectID:nil withLatestMessage:NO error:NO];
if (error) NSLog(#"CLIENT CONTROLLER: getJSON answer failed to decode answer with error:%#",[error localizedDescription]);
}
NSDictionary *finalResultToReturn = [NSDictionary dictionaryWithDictionary:finalResultAlloc];
[finalResultAlloc release];
return finalResultToReturn;
}
Don't forget to pack attributes with images to base64.
Finally, if u don't like to keep data, which u send in you mac app, u can send to u database using any database C api. I recommend to using core data to save receive data.

php -> JSON -> iPhone

I have an iPhone app which sends a request to a url posting a variable called submit:
+(NSMutableArray*)getQuestions:(NSString*)section from: (NSString*) url{
NSMutableArray *questions = [[NSMutableArray alloc] init];
//connect to database given by url
//NSError *error = nil;
//NSURLResponse *response = nil;
NSMutableString* myRequestString = [[NSMutableString string]initWithFormat:#"section=%#", section];
NSData *myRequestData = [NSData dataWithBytes: [myRequestString UTF8String] length: [myRequestString length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: url]];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
[request setHTTPMethod: #"POST"];
//post section
[request setHTTPBody: myRequestData];
//store them in the array;
return [questions autorelease];
}
My php file:
<?php
//connect to database
function connect() {
$dbh = mysql_connect ("localhost", "abc1", "12345") or die ('I cannot connect to the database because: ' . mysql_error());
mysql_select_db("PDS", $dbh);
return $dbh;
}
//store posted data
if(isset($_POST['section'])){
$dbh = connect();
$section = $_POST['section'];
$query = mysql_query("SELECT * FROM QUESTIONS WHERE sectionId = $section;") or die("Error: " . mysql_error());;
$rows = array();
while($r = mysql_fetch_assoc($query)) {
$rows[] = $r;
}
echo '{"questions":'.json_encode($rows).'}';
mysql_close();
}
?>
I have built a model class (Question) in objective c which has the exact properties that each row element has in the rows associative array.
My questions are:
1) How can I read the echo'd JSON array elements and their relative attributes in objective C?
2) How can I create an array of Question objects and map each one to an element in the rows array?
3) What do I have to write in my method "+(NSMutableArray*)getQuestions:(NSString*)section from: (NSString*) url" to capture the reply from the php (the echo)?
EDIT:
Here is the output of the php:
http://dev.speechlink.co.uk/David/get_questionstest.php
UPDATE
Changed method to use ASIHTTPRequest - Cannot deserialise JSON string:
//method to
+(NSDictionary*)getQuestions:(NSString*)sectionId from: (NSString*) url{
NSDictionary *questions;
NSURL *link = [NSURL URLWithString:url];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:link];
[request setPostValue:sectionId forKey:#"section"];
NSError *error = [request error];
[request startAsynchronous];
if (!error) {
//NSString *response = [request responseString];
//store them in the dictionary
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
NSString *json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
questions = [json objectFromJSONString];
NSLog(#"Data: %#", questions); //outputs Data: (null)
[json release];
[request release];
}else{
//UIAlertView to warn users there was an error
}
return questions;
}
Well, lets go through this one step at a time.
You can create a NSDictionary from JSON quite easily by using one of several different JSON parsing libraries. I really enjoy using JSONKit. Once you've imported JSONKit, into your project, you can do something like this:
NSString *url = #"http://dev.speechlink.co.uk/David/get_questionstest.php";
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
NSString *json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *questions = [json objectFromJSONString];
[json release];
Now you have an array filled with the questions in your example. Now you can loop through this array and fill your data with the data in the array. Now lets be practical. It would be easier if you just had to manage one object instead of four for each question, wouldn't it? Lets make a class that contains one question each instance.
Interface:
#interface Question : NSObject {
NSString *questionId;
NSString *question;
NSString *questionNumber;
NSString *sectionId;
}
#property(copy)NSString *questionID;
#property(copy)NSString *question;
#property(copy)NSString *questionNumber;
#property(copy)NSString *sectionId;
#end
And implementation:
#implementation Question
#synthesize questionId, question, questionNumber, sectionID;
#end
Now that's just a basic example. Nothing fancy. Now you can loop through the array you had before and create "question" objects that contain each question's data. For my purposes, suppose you have a NSMutableArray named questionsArray that contain the questions you want to use. We'll loop through the dictionary and add the questions from the dictionary into the questionsArray array.
for (NSDictionary *q in questions) {
/* Create our Question object and populate it */
Question *question = [[Question alloc]init];
question.questionId = [q objectForKey:#"questionId"];
question.question = [q objectForKey:#"question"];
question.questionNumber = [q objectForKey:#"questionNumber"];
question.sectionId = [q objectForKey:#"sectionId"];
/* Add it to our question (mutable) array */
[questionsArray addObject:question];
[question release];
}
Tada! Now you have an array filled with Question objects. Any time you want to look at a property on any of the question objects, you can just simply access that property. For example, to grab the first question's number, you can just do this:
NSString *q1Number = [questionsArray objectAtIndex:0].questionNumber;
Please note this is all untested, as I don't have my compiler with me. It should get you started, though. =)
Edit: You were doing your request completely wrong. Try this:
+(NSDictionary*)getQuestions:(NSString*)sectionId from: (NSString*) url{
NSDictionary *questions = nil;
NSURL *link = [NSURL URLWithString:url];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:link];
[request setPostValue:sectionId forKey:#"section"];
NSError *error = [request error];
[request startSynchronous];
if (!error) {
NSData *response = [request responseData];
NSString *json = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
questions = [json objectFromJSONString];
[json release];
} else{
//UIAlertView to warn users there was an error
}
[request release];
return questions;
Take a look at Stig Brautaset's excellent JSON parser at GitHub.
And there are even a couple of sample projects included.
From your PHP, one would expect the parser to produce and array of NSDictionary objects. I'm not sure what you mean by question 2, but you can then iterate through the array and create custom "Question" objects with the NSDictionary values.
Hope this helps.
Didn't see that you added a third question. This is answered in the "TweetStream" example above. I would suggest that you use the NSURLConnectionDelegate methods as described by Apple.

Sending form data via HTTP Post [Objective C]

I have a form data from an iphone app that needs to send HTTP Post variables to a URL.
The thing is, I've been told not to use setHTTPBody, but am unsure of how else to do it as every example I see uses setHTTPBody; even those that use POST methods.
To make things matters a little more complicated, the URL/webpage requires a submit=true and action=enquiry in the post variables.
Here's what I have so far.
NSString *formContactName = [self contactName];
NSString *formEmail = [self email];
NSString *formPhone = [self phone];
NSString *formComments = [self comments];
// The above data is fine, as explored here.
NSLog(#"formContactName = %#", formContactName);
NSLog(#"formEmail = %#", formEmail);
NSLog(#"formPhone = %#", formPhone);
NSLog(#"formComments = %#", formComments);
// Setup request
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:advertURL]];
[request setHTTPMethod:#"POST"];
// set headers
NSString *contentType = [NSString stringWithFormat:#"text/plain"];
[request addValue:contentType forHTTPHeaderField:#"Content-Type"];
// setup post string
NSMutableString *postString = [[NSMutableString alloc] init];
[postString appendFormat:#"contactname=%#", formContactName];
[postString appendFormat:#"&email=%#", formEmail];
[postString appendFormat:#"&phone=%#", formPhone];
[postString appendFormat:#"&comments=%#", formComments];
[postString appendFormat:#"&submit=yes"];
[postString appendFormat:#"&action=enquiry"];
// I've been told not to use setHTTPBody for post variables, but how else do you do it?
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
// get response
NSHTTPURLResponse *urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponse
error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response code: %d", [urlResponse statusCode]);
if ([urlResponse statusCode] >=200 && [urlResponse statusCode] <300)
{
NSLog(#"Response ==> %#", result);
}
[result release];
[error release];
I always get a 200 result, which is good. But the response back indicates that the Post variables are not getting through.
The response back has a field in it called "enquirysent" and its always blank. If the Post variables are successful, it should return a "1" or true statement.
"enquirysent": ""
Therefore, my question is: How do I force the HTTP-POST variables in the above request?
Thanks.
you can use ASIHTTPRequest to simplify:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"Ben" forKey:#"first_name"];
[request setPostValue:#"Copsey" forKey:#"last_name"];
[request setFile:#"/Users/ben/Desktop/ben.jpg" forKey:#"photo"];

Creating an MJPEG Viewer Iphone

I'm trying to make a MJPEG viewer in Objective C but I'm having a bunch of issues with it.
First off, I'm using AsyncSocket(http://code.google.com/p/cocoaasyncsocket/) which lets me connect to the host.
Here's what I got so far
NSLog(#"Ready");
asyncSocket = [[AsyncSocket alloc] initWithDelegate:self];
//http://kamera5.vfp.slu.se/axis-cgi/mjpg/video.cgi
NSError *err = nil;
if(![asyncSocket connectToHost:#"kamera5.vfp.slu.se" onPort:80 error:&err])
{
NSLog(#"Error: %#", err);
}
then in the didConnectToHost method:
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
NSLog(#"Accepted client %#:%hu", host, port);
NSString *urlString = [NSString stringWithFormat:#"http://kamera5.vfp.slu.se/axis-cgi/mjpg/video.cgi"];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
//set headers
NSString *_host = [NSString stringWithFormat:host];
[request addValue:_host forHTTPHeaderField: #"Host"];
NSString *KeepAlive = [NSString stringWithFormat:#"300"];
[request addValue:KeepAlive forHTTPHeaderField: #"Keep-Alive"];
NSString *connection = [NSString stringWithFormat:#"keep-alive"];
[request addValue:connection forHTTPHeaderField: #"Connection"];
//get response
NSHTTPURLResponse* urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response Code: %d", [urlResponse statusCode]);
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
NSLog(#"Response: %#", result);
//here you get the response
}
}
This calls the MJPEG stream, but it doesn't call it to get more data. What I think its doing is just loading the first chunk of data, then disconnecting.
Am I doing this totally wrong or is there light at the end of this tunnel?
Thanks!
Try loading the mjpeg in a UiWebView, it should be able to play it natively.
Assuming you have a UiWebView called "myWebView", something like this should work:
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://kamera5.vfp.slu.se/axis-cgi/mjpg/video.cgi"]];
[myWebView loadRequest:urlRequest];
I hope that helps!
the main problem is that webkit never relase the data, so after a while it explode.
That would probably best be done with JavaScript since there isn't a good way to communicate with UIWebView otherwise.