Zip file not created properly in iOS - ios

I am writing all the NSLOG's to a text file and post it to the server on click of a table view cell . I convert the text file to zip file before I post it using NSURLConnection . However , There is Some garbage data present inside the Zip file posted , But the text file has the correct content. I am using SSZipArchive, The code that I use to post the file is
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"Logger.txt"]];
NSString* zipfile = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"Logger.zip"]];
//create zip file, return true on success
BOOL isZipCreated=[SSZipArchive createZipFileAtPath:zipfile withContentsOfDirectory:logFilePath];
if (isZipCreated) {
NSLog(#"Zip file Created at Path : %#",zipfile);
NSString *contentOfZipFile = [NSString stringWithContentsOfFile:zipfile encoding:NSUTF8StringEncoding error:NULL];
NSData *zipData = [contentOfZipFile dataUsingEncoding:NSUTF8StringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[zipData length]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:finalURL]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/zip" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:zipData ];
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
}
else {
NSLog(#"Zip create error");
}
Any assistance would be of great help.

You can use this library Objective-Zip, actually I have used this and its working fine for me.
Creating a Zip File:
ZipFile *zipFile= [[ZipFile alloc] initWithFileName:#"Logger.zip" mode:ZipFileModeCreate];
Adding a file to a zip file
ZipWriteStream *stream= [zipFile writeFileInZipWithName:#"Logger.txt" compressionLevel:ZipCompressionLevelBest];
[stream writeData:abcData];
[stream finishedWriting];
Reading a file from a zip file:
ZipFile *unzipFile= [[ZipFile alloc] initWithFileName:#"Logger.zip" mode:ZipFileModeUnzip];
[unzipFile goToFirstFileInZip];
ZipReadStream *read= [unzipFile readCurrentFileInZip];
NSMutableData *data= [[NSMutableData alloc] initWithLength:256];
int bytesRead= [read readDataWithBuffer:data];
[read finishedReading];
Hope this code will help you :)
Happy Coding!! ;)

Related

How to zip a text file and post it using NSURLConnection in objective-c

I have a text file in which I write all the NSLOG's and I post it to the server whenever required. Since I want to optimise the size of the file that is sent to the server , I want to zip the text file . I referred a lot of examples but could not clearly understand . This is my code to create the file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName =[NSString stringWithFormat:#"Logger.txt"];
NSString *logFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding],"a+",stderr);
and this is the code to post the file to the server.
NSString *finalURL = [self getSupportServletURL:persist];
NSURL *url = [NSURL URLWithString:finalURL];
NSMutableURLRequest * requests = [[NSMutableURLRequest alloc]initWithURL:url];
[requests setHTTPMethod:#"POST"];
[requests setValue:#"text" forHTTPHeaderField:#"Content-type"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Logger.txt"];
NSString *content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
LogInfo(#"Data being posted to server %#",finalURL);
LogTrace(#"Post Data : Data being posted to server \n%#",content);
[requests setTimeoutInterval:60.0];
[requests setHTTPBody:[content dataUsingEncoding:NSUTF8StringEncoding]];
[requests setValue:[NSString stringWithFormat:#"%lu",(unsigned long)[content length]] forHTTPHeaderField:#"Content-Length"];
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:requests delegate:self];
and this works perfectly. Can anyone help me in converting this to a zip file ( including the things that need to be included in .m file & .h file ) and posting it to the server . Thank You in advance.
Create logger file following way. I just created file in different directory instead of document directory so we can zip that directory.
//creating logger file in document directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//logger file name
NSString *fileName =[NSString stringWithFormat:#"Logger.txt"];
//we will add log file in "LogFiles" directory so we can zip that directory
NSString *logFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"/LogFiles/%#",fileName]];
//"LogFiles" directory path
NSString *LogFilesDirectory = [documentsDirectory stringByAppendingPathComponent:#"/LogFiles"];
NSError *error;
//create "LogFiles" directory if not created
if (![[NSFileManager defaultManager] fileExistsAtPath:LogFilesDirectory])
[[NSFileManager defaultManager] createDirectoryAtPath:LogFilesDirectory withIntermediateDirectories:NO attributes:nil error:&error];
//writing logger file
freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding],"a+",stderr);
Now
#import "SSZipArchive.h" in viewController.m
To create zip file use following code
//getting logger.txt file path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"/LogFiles"]];
NSString* zipfile = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"/LogFiles/Logger.Zip"]];
//create zip file, return true on success
BOOL isZipCreated=[SSZipArchive createZipFileAtPath:zipfile withContentsOfDirectory:logFilePath];
if (isZipCreated) {
NSLog(#"Zip file Created at Path : %#",zipfile);
NSData *zipData = [NSData dataWithContentsOfFile:zipFile]; // note, autorelease object
NSString *postLength = [NSString stringWithFormat:#"%d", [zipData length]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/zip" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:zipData];
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:requests delegate:self];
}
else
{
NSLog(#"Zip create error");
}

Post Request to alchemy API in iOS8

Im trying to use the API call TextGetRankedNamedEntities http://www.alchemyapi.com/api/entity/textc.html#rtext
Here is my relevant code:
NSString *data = #"Data I want analyzed";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"result.txt"];
[data writeToFile:appFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
//I have verified the data is in the file
NSString *queryString = [NSString stringWithFormat:#"http://access.alchemyapi.com/calls/text/TextGetRankedNamedEntities?apikey=MY_API_KEY&showSourceText=1"];
NSMutableURLRequest *theRequest=[NSMutableURLRequest
requestWithURL:[
NSURL URLWithString: queryString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
//Set request method to post
[theRequest setHTTPMethod:#"POST"];
NSString *post = [NSString stringWithFormat:#"&text=%#", appFile];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
[theRequest setHTTPBody:postData];
my result for this request is:
<?xml version="1.0" encoding="UTF-8"?>
<results>
<status>OK</status>
<usage>By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www.alchemyapi.com/company/terms.html</usage>
<url></url>
<language>english</language>
<text>/var/mobile/Containers/Data/Application/6C00A4F8-4DEE-44F2-9DBF-7568CEF72054/Documents/result.txt</text>
<entities>
</entities>
</results>
It appears that the data that is being send is the file path and not that actual contents of the file.
EDIT: Solved, Leaving the question for possible feedback and best practices for using HTTTP requests in iOS as I am new to both.
Change:
NSString *post = [NSString stringWithFormat:#"&text=%#", appFile];
To:
NSString *post = [NSString stringWithFormat:#"&text=%#", data];
It didn't occur to me to try this before posting the question because I had previous tried to do this but at that point I was sending the request with the GET method not the POST method.

AFNetworking - json file uploading on iOS

I am starting to grow grey hairs here:-)
I have this code, which was based from an image upload - which there are so many of on the web, but I need it to upload a .json file - the file generates correctly to appear in my Documents Directory, but I need it to be uploaded to my server.
_myJSON= [NSMutableString stringWithFormat:#"{ \" %# \" : [ ", _menuCategoryPickerFld.text];
[_myJSON appendString: [NSString stringWithFormat: #"{ \"name\" : \"%#\", \"model\" : \"%#\", \"size\" : \"%#\" }",
_menuTitlePickerFld.text, _menuSubTitlePickerFld.text, _menuPricePickerFld.text]];
[_myJSON appendString: #" ]}"];
NSData *data = [_myJSON dataUsingEncoding:NSUTF8StringEncoding];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"testJSON2.json"];
[data writeToFile:appFile atomically:YES];
NSString *tempString = #"http://thepalmsmarket.co.nz/jsonExports/uploads/";
NSURL *remoteURL = [NSURL URLWithString:tempString];
// Back to NSData
NSData *convertedFile = [_myJSON dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:remoteURL];
[request setHTTPMethod: #"POST"];
[request setHTTPBody:convertedFile];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite)
{
}];
[operation start];
Ok so I think some of the formatting is wrong, but also for files to be uploaded don't I need to add the username and password of my web-server in my app somewhere, so it can be authenticated for the upload??

Need to detect when app is unable to connect to server when uploading JSON document in iOS

I am uploading a JSON document from my app to a server on the web, and I am able to do this successfully. However, what I need to do now is detect when there is no WiFi or 3G connectivity and prompt the user with an alert that informs the user that the app is unable to connect, and then give them the option to save the JSON document as a .plist file locally.
Here is the code that I have thus far:
This is my method that uploads my JSON document to the server:
- (void) sendJsonDoc:(NSString *)jDoc {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://myWebsite.php"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[request setValue:[NSString stringWithFormat:#"%d", [jDoc length]] forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:[jDoc dataUsingEncoding:NSUTF8StringEncoding]];
[NSURLConnection connectionWithRequest:request delegate:self];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
int code = [httpResponse statusCode];
NSLog(#"%d", code);
}
Here is the code that I have in order to save the JSON document locally as a plist file:
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:#"jsonDoc.plist"];
// If the file doesn't exist in the Documents Folder, copy it.
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:#"jsonDoc" ofType:#"plist"];
[fileManager copyItemAtPath:sourcePath toPath:path error:nil];
}
// Load the Property List.
NSString *loadJSON = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
How do I detect in my sendJsonDoc method when there is no connection and issue an alert to the user that prompts them that there is no connection, and if they want to save the document locally?
Check out the Reachability framework/library.
tonymillion made a nice version of the Apple supplied one that has been adapted to use ARC and adds support for blocks as well. The readme on github also explains how you can subscribe to notifications for the change of connection :)
Check out the project here

iPhone: Error uploading audio wav bytes data to server

I am developing an iOS application. I have to send an audio file to our server programmatically. I am using the following code to send an sample wav audio file to server. Our server accepts only audio file in signed bytes array format for receiving.
NSURL *urlPath = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:#"Crash" ofType:#"wav"]];
NSString *wavbundlepath = [urlPath absoluteString];
NSLog(#"wavbundlepath: %#",wavbundlepath);
NSData *bytes = [wavbundlepath dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"bytes: %#",bytes);
NSString *recordPostLength = [NSString stringWithFormat:#"%d", [bytes length]];
NSMutableString *urlstr = [NSMutableString stringWithFormat:#"%#", #"http://www.mywebserver/api/UploadFile?Name="];
[urlstr appendString:#"crash"];
[urlstr appendFormat:#"&MemberID=%d", 0];
[urlstr appendFormat:#"&Type=%#",#"Recording"];
[urlstr appendFormat:#"&client=%#",#"ios"];
NSLog(#"urlstr.......%#",urlstr);
NSMutableURLRequest *recordRequest = [[NSMutableURLRequest alloc] init] ;
[recordRequest setURL:[NSURL URLWithString:urlstr]];
[recordRequest setHTTPMethod:#"POST"];
[recordRequest setValue:recordPostLength forHTTPHeaderField:#"Content-Length"];
[recordRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[recordRequest setHTTPBody:bytes];
NSURLResponse *recordResponse;
NSError *recordError;
NSData *recordResponseData = [NSURLConnection sendSynchronousRequest:recordRequest returningResponse:&recordResponse error:&recordError];
NSString *recordResp = [[NSString alloc]initWithData:recordResponseData encoding:NSUTF8StringEncoding];
NSLog(#"recordResp:%#", recordResp);
But the problem is, always receving "Input string is not correct." response error.
I am not very much aware of uploading audio bytes to server. Could someone please check this code and tell me this is valid code or not for uploading a wav audio bytes array to server?
Thank you.
UPDATED CODE
I tried below code as my server side engineer said not to have any other things post body, and it works fine and getting positive response. But, the server is not able to work with format NSData bytes (32 bit elements) what i'm sending, because server side its implemented to receive only array of bytes or signed bytes data format only.
NSURL *urlPath = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:#"Temp" ofType:#"wav"]];
NSString *wavbundlepath = [urlPath absoluteString];
NSLog(#"wavbundlepath: %#",wavbundlepath);
NSData *bytes=[NSData dataWithContentsOfURL:urlPath];
NSLog(#"bytes: %#",bytes);
NSString *recordPostLength = [NSString stringWithFormat:#"%d", [bytes length]];
NSMutableString *urlstr = [NSMutableString stringWithFormat:#"%#", #"http://www.myserver.com/api/UploadFile?Name="];
[urlstr appendString:#"Temp"];
[urlstr appendFormat:#"&MemberID=%d", 0];
[urlstr appendFormat:#"&Type=%#",#"Recording"];
[urlstr appendFormat:#"&client=%#",#"ios"];
NSLog(#"urlstr.......%#",urlstr);
NSMutableURLRequest *recordRequest = [[NSMutableURLRequest alloc] init] ;
[recordRequest setURL:[NSURL URLWithString:urlstr]];
NSInputStream *dataStream = [NSInputStream inputStreamWithData:bytes];
[recordRequest setHTTPBodyStream:dataStream];
[recordRequest setHTTPMethod:#"POST"];
NSURLResponse *recordResponse;
NSError *recordError;
NSData *recordResponseData = [NSURLConnection sendSynchronousRequest:recordRequest returningResponse:&recordResponse error:&recordError];
NSString *recordResp = [[NSString alloc]initWithData:recordResponseData encoding:NSUTF8StringEncoding];
NSLog(#"recordResp:%#", recordResp);
recordResponceJson = [recordResp JSONValue];
NSLog(#"recordResponceJson = %#",recordResponceJson);
recId = [recordResponceJson valueForKey:#"ID"];
NSLog(#"recId....%#", recId);
Could someone please guide me, how i can send array of bytes in this http post?
There are a couple problems:
First how you're reading the file will not return a valid WAV file:
You should use [NSData dataWithContentsOfURL:] to read the bytes. The way you're reading them it will try to convert the bytes into characters. This will corrupt your wav file.
Second, the content-type of the POST body is probably incorrect. See the line:
[recordRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
The audio bytes would not be encoded in x-www-form-urlencoded format. It is more likely that the server would accept a audio/wav or application/octet-stream content type. Check with your server developers to see exactly what the server is expecting.
Also, you may want to check out the NSMutableURLRequest method called setHTTPBodyStream: that lets you send a file without having to load the entire thing into memory.

Resources