iphone download image with variable using ASIHTTPRequest - iphone

I got stuck something annoying.
I uploaded images to server it's ok.
However, when i try to download image from server i want to get image with string variable. here is my php code server side
....
echo "image_getting;";
$fullPath = $_POST['download_image'];
echo file_get_contents($fullPath);
....
if i remove first line from my server [request responseData] working correctly.
However, i want to also get "image_getting;" because i am also downloading some different types.
if i can clear, iphone side
when i say
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSString *responseString = [request responseString];
NSLog(#"%#",responseString);
NSArray *resultResponseArray = [responseString componentsSeparatedByString:#";"];
if([[resultResponseArray objectAtIndex:0] isEqualToString:#"image_getting"])
{
NSData *responseData = [request responseData];
UIImage * image = [UIImage imageWithData:aData];
.......
}
else if...
....
}
as you can see above response data also taking echo "image_getting" how do i split it.
I tried to convert and split them it didn't work.
I should say, i am very bad with php.
I will be appreciated, if someone help me.
Thanks
EDIT:Solution Php side
header('X-Return: image_getting;');
$fullPath = $_POST['download_image'];
echo file_get_contents($fullPath);
iphone side
NSLog(#"header %#",[[request responseHeaders] objectForKey:#"X-Return"]);

Why don't you put the "image_getting" into a HTTP header in the response instead? That would make the parsing much easier - you can then retrieve the header:
NSString *whatever = [[request responseHeaders] objectForKey:#"X-Whatever"];
and then [request responseData] will only contain the image.

Related

Base64 encoded image corrupted during transfer to server

For some reason i can't upload a jpeg file to a server using the post method in NSURLRequest
I have an android app that uses the same php code and can upload and download images fine by converting the image to a byte array and then using base64 encoding to send and receive.
My iPhone app downloads the image fine, The php script encodes using base64 and i use a base64 decoder in my iPhone app which I then convert into an image. This works fine.
However the uploading of the image doesn't work.
I convert the image to a base64 encoded string (I've used a few different methods for the base64 encoding and they all give the same result) then I post to the server, decode on the server side and save to file on the server.
The resulting decoded file on the server is a corrupt jpeg image. The corrupt file size is 3 times as many bytes as it should be.
The base64 encoded string generated for the upload is also very different to the base64 encoded string generated when downloading the same jpeg file from the server (ie. the valid image file that I uploaded using an ftp service).
My code is shown below along with the php script to receive the image.
I believe there is something happening with escaping characters which is causing the base64 string to become corrupted during the transfer but can't work it out.
Why is my base64 string being corrupted during transfer?
NSString* comments = #"comments to go with image";
NSData *data = UIImageJPEGRepresentation(_imageView.image, 1);
NSString *base64EncodedImage = [NSString base64StringFromData: data length: data.length];
//load the team posts so we know what items have been posted and what haven't
NSMutableDictionary *postDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
comments, #"comment",
base64EncodedImage , #"image",
nil];
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in postDict) {
NSString *part = [NSString stringWithFormat: #"%#=%#", key, [postDict objectForKey:key]];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
NSData *postData = [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
NSString* url = #"http://www.scroppohunt.com/upload.php";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
_data = [[NSMutableData data] init];
}
and the php script that receives the image
<?php
$comments = $_REQUEST['comment'];
//do some database stuff with the comments
////////////////////////////////////////
//save the file to the images folder
///////////////////////////////////////////
$base=$_REQUEST['image'];
if(strlen($base) > 0)
{
// base64 encoded utf-8 string
$binary=base64_decode($base);
$file = fopen("postImages/test.jpg", 'wb');
fwrite($file, $binary);
fclose($file);
}
//display the bae64 encoded string taht was uploaded
echo $base;
?>
Well, it's been a while when you asked this question, but if anyone (like me) find this question, this may help:
In your Base64 encoded image, you should replace all occurrences of "+" character, with "%" character. Translated into code, it would be:
NSString* encodedImageString = [base64EncodedImage stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
Then, instead of adding base64EncodedImage in postDict, you should add encodedImageString.
That way, your postDict will look like this:
NSMutableDictionary *postDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
comments, #"comment",
encodedImageString , #"image",
nil];
I think this will solve the problem, at least, was for me.
Cheers.
I also had this problem. For me, what was happening was that all the "+" were replaced with "space" after being sent to the server. There was no other such corruption:
Try Changing content type.
[request setValue:#"image/jpeg" forHTTPHeaderField:#"Content-Type"];

how to cache xml data on iphone

I am trying to use the ASIDownloadCache from the ASIHTTPRequest library. I think I have it almost set up but the data I am printing to the log is a bunch of numbers.. I think it might be a formatting problem.. but I would like to run it past someone with more experience first to make sure I'm doing it correctly and then to hopefully help me fix the issue.
The code belows shows you how I am setting up my cache, I am using this view for several data sets, hence the need to use an if statement so that I am only setting up the cache on specific data.
- (IBAction)setRequestString:(NSString *)string
{
//Set database address
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"http://***.***.***.***:8888/codeData/"]; // iphone development
//PHP file name is being set from the parent view
[databaseURL appendString:string];
//call ASIHTTP delegates (Used to connect to database)
NSURL *url = [NSURL URLWithString:databaseURL];
checkDataSet = [[NSString alloc] initWithFormat:string]; //Loads ICMfg.xml into checkDataSet for setting up cache
//Create If statments here
if ([checkDataSet isEqualToString:#"ICMfg.xml"]) {
//Cache stuff goes in here
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request setSecondsToCache:60*60*24*30]; // Cache for 30 days
[request setDelegate:self]; // A delegate must be specified
[request startSynchronous];
//[request setDidFinishSelector:#selector(requestFinished:)]; // And an appropriate
}
else
{
//this else statments lets all of the other datasets come through here
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
}
From here, when [checkDataSet isEqualToString:#"ICMfg.xml"] is true it will set the cache parameters and then calls the following method where I get everything ready to parse my information
- (void)requestFinished:(ASIHTTPRequest *)request
{
if ([checkDataSet isEqualToString:#"ICMfg.xml"]) {
BOOL success = [request didUseCachedResponse];
NSLog(#"------------>>>>>>> Success is %#\n", (success ? #"YES" : #"NO"));
responseString = [request responseString];
capturedResponseData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", capturedResponseData); //this prints out the weird data.
[self startTheParsingProcess:capturedResponseData];
}
else
{
responseString = [request responseString]; //Pass requested text from server over to NSString
capturedResponseData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
[self startTheParsingProcess:capturedResponseData];
}
}
From here, I check my nslog to see the result of that NSlog and it spits out a bunch of numbers, below is a small section of the output. The next step for me is to check to see if anything is actually being parsed.. and also to see if the cache is working or not.. then I need to figure out hopefully with your help how to format the data correctly if thats my main problem..
also I would like to ask how to get this working asynchronously as currently I can only get it to work synchonosly.
2011-11-09 09:29:55.216 code[3968:207] ------------>>>>>>> Success is YES
2011-11-09 09:29:55.239 code[3968:207] <3c3f786d 6c207665 7273696f 6e3d2231 2e302220 656e636f 64696e67 3d225554 462d3822 3f3e0d0a 3c494345 6e673e3c 52657375 6c742044 42566572 73696f6e 3d223132 33223e3c 5461626c 65733e3c 5461626c 65205461 626c654e 616d653d 2249434d 6667223e 3c526f77 733e3c52 6f77204d 414e5546 41435455 52455249 443d2237 30362220 4d414e55 46414354 55524552 3d22412d 445a4722 2049534c 4f434b4d 414e5546 41435455 5245523d 22462220 49535645 4849434c 453d2246 223e3c2f 526f773e 3c526f77 204d414e 55464143 54555245 5249443d 22333138 22204d41 4e554641 43545552 45523d22 412e522e 452e2220 49534c4f 434b4d41 4e554641 43545552 45523d22 46222049
any help would be greatly appreciated.
I don't see anything that immediately sticks out in your code as wrong.
The NSLog() is printing an NSData object, which is binary data so the hexadecimal numbers you are seeing are the representations of the bytes which is exactly what you would expect.
The NSData Class Reference:
description
Returns an NSString object that contains a hexadecimal
representation of the receiver’s contents.
(NSString *)description
Return Value
An NSString object that contains a hexadecimal representation of the receiver’s contents in
NSData property list format.
If you want to print out the string representation of this data, use:
NSString *capturedResponseString = [NSString stringWithUTF8String:[capturedResponseData bytes]];

iPhone not downloading file

I have a tested and working php script that pulls from a db and returns as an XML.
I have used ASIHTTPRequest to make a POST to the php script successfully.
I have looked for online help to get this to work. From what I understand, all the code is solid. It compiles properly, runs without problem, even makes the request without problem. I get no errors.
Since I have thoroughly tested and successfully used the php, I assume the break is on the iPhone side.
I do not understand why it does not download the XML file to the specified location.
Any insight would be greatly appreciated.
// Create the request
NSURL *url=[[NSURL alloc]initWithString:#"http://localhost:8888/Project/script.php"];
ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url]retain];
// gather *ALL* data present
if ( [txtEmail.text length] > 0 )
[request setPostValue:txtEmail.text forKey:#"email"];
if ( [txtFName.text length] > 0 )
[request setPostValue:txtFName.text forKey:#"firstname"];
if ( [txtID.text length] > 0 )
[request setPostValue:txtID.text forKey:#"id"];
if ( [txtLName.text length] > 0 )
[request setPostValue:txtLName.text forKey:#"lastname"];
[request setDidFailSelector:#selector(requestFailed:)];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDownloadDestinationPath:#"/Library/Project/dbInfo.xml"];
[request setDelegate:self];
[request startSynchronous];
[request release];
[url release];
a few points on your code:
Why are you using a POST request to download a file? usually downloading is done via a GET request (if we're talking REST). You could use a simple ASIHTTPRequest + adding your post values as URL-Parameters (+ handle it on the php side accordingly).
you are allocating and retaining your ASIFormDataRequest instance, but only releasing it once -> results in a memory leak. (for every alloc/copy/retain -> release it).
To answer you question:
i think the downloadDestinationPath is wrong (the application has no permissions to write there).
Better:
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [docDir stringByAppendingPathComponent:#"dbInfo.xml"];
[request setDownloadDestinationPath:path];
Now your "dbInfo.xml" File is saved in the documents folder of your application.
If you're running your app in the simulator, you can find the directory at:
~/Library/Application Support/iPhone Simulator/IOS_SDK_VERSION/Applications/APP_UID/Documents
And:
if you implement the downloadProgressDelegate: request:didReceiveBytes: method, you can check if you're actually receiving data:
-(void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes {
NSLog(#"received bytes ..") ;
}

Problem sending images POST

For several days, I look for what's wrong in my code but without success, and now I really want to know what's wrong.
The problem is that I want to send an UIImage from my Iphone to my server, but I receive a blank image on my server everytime... I'm not sure, but I think the problem come from the image that I convert. The UIImage come from the method takePicture.
Please check my code :
First I call takePicture and :
- (void)imagePickerController:(UIImagePickerController *)aPicker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.testImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
testImage is a property of my ViewController.
Then I make this to send the UIImage :
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(testImage)];
NSURL *url = [NSURL URLWithString:#"http://myserver/mytest.php"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addData:imageData withFileName:#"tmp.png" andContentType:#"image/png" forKey:#"userfile"];
[request setRequestMethod:#"POST"];
[request setDelegate:self];
[request startAsynchronous];
and to see the result :
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
NSLog(#"response: %#", responseString);
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
NSLog(#"Request Failed Error: %#", error);
}
and then I receive a blank image on my server...
Please help me ='(
I think you're actually sending a URL encoded POST body, as opposed to a multi-part POST body, which is required to send data like you want. So you just need to do the following before you start the request:
request.postFormat = ASIMultipartFormDataPostFormat;
The issue came from the high resolution image. My connection was too slow. When I'm using wifi the code works.
Mate,
look at your code here:
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(testImage)];
you can change the picture quality by adding a number in the bracket for the dpi you would like it to be, for example, if i wanted it to be in 90 dpi quality i would have written it like this: [NSData dataWithData:UIImagePNGRepresentation(testImage,90)]
i noticed now that your picture is in .PNG format , i always worked with .JPEG and it worked
so i think you should give it a try...
good luck

Three20 + JSON Parsing

I'm using Three20 and want to use JSON to populate my TTPhotoViewController.
If I go to a web address, let's say,
www.bbc.com/jsonoutput
I get the following
{"name":"MyName","curNiceDate":"Wed 29 Dec 10","images":["UK\/2010\/12\/29\/1.jpg","US\/2010\/12\/29\/2.jpg","EU``\/2010\/12\/29\/3.jpg","FR\/2010\/12\/29\/4.jpg","FR\/2010\/12\/29\/5.jpg","FR\/2010\/12\/29\/6.jpg","FR\/2010\/12\/29\/7.jpg","FR\/2010\/12\/29\/8.jpg","FR\/2010\/12\/29\/9.jpg"]}
I want to pick out images which are in www.bbc.com/images/.
All those directories are locations of images relevant from the above address. How would I go about pulling out this information from the JSON output and make it into a URL which will look like this
www.bbc.com/UK/2010/12/29/1.jpg
www.bbc.com/US/2010/12/29/2.jpg
www.bbc.com/EU/2010/12/29/3.jpg
www.bbc.com/FR/2010/12/29/4.jpg
So I can feed it into the TTPhotoView Picker.
Any help please?
I've been happy with TouchJSON, it's also very easy to use. I'm using it in conjunction with ASIHTTPRequest.
Here's a quick modification of my code to relate to your question.
- (IBAction)getImages{
NSURL *url = [NSURL URLWithString:#"www.bbc.com/jsonoutput"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request{
NSError *error;
NSDictionary *bbcData = [[CJSONDeserializer deserializer] deserializeAsDictionary:[request responseData] error:&error];
//TODO: do something with the error
NSArray *images = [bbcData objectAtIndex:#"images"];
NSLog(#"%#", images);
}
- (void)requestFailed:(ASIHTTPRequest *)request{
NSError *error = [request error];
//TODO: do something with the error
}
https://github.com/stig/json-framework It's super easy to use. If you get stuck just look at how I used it in my code here
json-framework is good use it.