Now I know that xCode automaticly does the GZip decrompession for you within:
NSData *data = [NSData dataWithContentsOfURL:URL];
And it does work if I point to a Gzip file on my server. But since my content is dynamic, I have a PHP script that rather then create a gzip file like so:
$zp = gzopen($file, "r");
$data = gzread($zp, $filesize);
gzclose($zp);
I encode my own data with:
echo gzencode($data, 9);
With this I add the following headers:
header("Content-Type: application/x-gzip");
header("Content-Encoding: gzip");
header("Accepts-Encoding: gzip");
When I browse to the URL, my browser wants to download the file automatically and I am able to unzip it on my Mac and view it's content. However when I try to read it through xCode it won't work.
NSData *data = [NSData dataWithContentsOfURL:URL];
NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog (content); //returns only data when pointed directly to a Gzip file
Am I forgetting something?
If you download something with content type application/x-gzip, the url loading system will not decompress it for you. I think the data that you received is still gzip encoded.
You can use my NSData additions to deal with this. See http://github.com/st3fan/cocoa-utils/blob/master/src/NSDataGZipAdditions.m
Related
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"];
I want to know whether using ASIHTTPRequest we can unzip a .zip downloaded file or it can only
unzip .gzip compressed file.
Please let me know because if ASIHTTPRequest cannot unzip .zip compressed file then I will have to use third party api like ZipArchive to unzip the downloaded file.
Thanks
Why not using gzip compressed HTTP communication which would be transparently decoded for you by ASI (and virtually all other HTTP access frameworks).
ASIHTTP supports decompression, for example -
- (IBAction)grabURL:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
// YES is the default, you can turn off gzip compression by setting this to NO
[request setAllowCompressedResponse:YES];
[request startSynchronous];
BOOL *dataWasCompressed = [request isResponseCompressed]; // Was the response gzip compressed?
NSData *compressedResponse = [request rawResponseData]; // Compressed data
NSData *uncompressedData = [request responseData]; // Uncompressed data
NSString *response = [request responseString]; // Uncompressed data as a string
}
UPDATE: incase asi does not support zip file decompression then I've used ZipArchive with success in the past.
It's pretty ligthweight and simple to use, supports password protection, multiple files inside a ZIP, as well as compress & decompress. so you need to first fetch the zip file through asi and then unzip is using ziparchive.
The basic usage is:
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"ZipFileName" ofType:#"zip"];
ZipArchive *zipArchive = [[ZipArchive alloc] init];
[zipArchive UnzipOpenFile:filepath Password:#"xxxxxx"];
[zipArchive UnzipFileTo:{pathToDirectory} overWrite:YES];
[zipArchive UnzipCloseFile];
[zipArchive release];
I have many files html type. Now i want to get content of them. But the text is not UTF8 format so stringWithContentOfFile function return nil. The problem is i can't convert text of file to UTF8 because there are many files. I tried use WebView but not success. There are any way to read files?
Get the data using dataWithContentsOfFile: method and then convert it into an NSString object using initWithData:encoding: method. You can provide the encoding there.
NSData * data = [NSData dataWithContentsOfFile:filePath];
NSString * fileInString = [[NSString alloc] initWithData:data encoding:yourEncoding];
In order to improve the client/server behaviour, I'm looking for adapt my iphone client code to proceed ziped responses.
The server adapt the SOAP response ziped.
I was looking how to uncompress the response but didn't work for me.
The first solution I studied was the ZipArchive, explained here, solution (from minizip) but it is focus on filesystem compression.
And I just need to uncompress a NSString.
After that I checked this second approach:
NSData *decodedGzippedData = [NSData dataFromBase64String:encodedGzippedString];
NSData* unGzippedJsonData = [ASIHTTPRequest uncompressZippedData:decodedGzippedData];
NSString* unGzippedJsonString = [[NSString alloc] initWithData:unGzippedJsonData encoding:NSASCIIStringEncoding];
But didn't work for me, because in the actual version the NSData dataFromBase64String didn't exists.
Now I'm working with the third response of the previous question, anybody knows which library or framework I need to install in order to import Base64.h and NSData+Compression.h ¿? Used in this other potencial solution
The solution was the next.
Install the next libraries to your project:
Base64.h // You can find it here
NSData+Compression.h // You can find it here
Use the code of one of the previous solutions
#import "Base64.h"
#import "NSData+compression.h"
...
// decoding the base64 ziped message
Byte inputData[[stringValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
[[stringValue dataUsingEncoding:NSUTF8StringEncoding] getBytes:inputData];
size_t inputDataSize = (size_t)[stringValue length];
size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);
Byte outputData[outputDataSize];//prepare a Byte[] for the decoded data
Base64DecodeData(inputData, inputDataSize, outputData, &outputDataSize);
// inflate the original string using gzip
NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];
NSData* result = [theData gzipInflate];//make bigger==gunzip
// Return the result
return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
Hey, Is it correct to initialize an NSData with a zip file? I want to convert a zip file into NSData and construct another file with the data (in simple language 'copy it'). I have the code as:
NSURL *theFileUrl = [NSURL URLWithString: #"file://localhost/Users/xxx/Desktop/testZippedFile.zip"];
NSData *data = [NSData dataWithContentsOfURL: theFileUrl];
When I, NSLog(#"Data: %#", data) , i do get some output but when I try to initialize an NSString with this data, it doesn't work:
NSString *str = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
`NSLog(#"String: %#", string)`
I get the log as: String: PK
Can anyone point out my mistakes please.
Thanks in advance!
Why do it that way? NSFileManager will do it for you :)
[[NSFileManager defaultManager] copyItemAtPath:oldPath toPath:newPath error:nil];
However, this only works for files that are local - if you want to copy a file from a server, you should have a look at NSURLConnection to load the data and then NSData's writeToFile:atomically: method to save the contents to the file system (found here.)
PK is the output you should expect.
The first 2 Characters in every zip-file are PK. Then there are some unprintable chars and at some point after those there is a character with a value of 0
If you create an NSString out of NSData all values up to the first 0-value are taken into account.
NEVER convert binary data into NSString.