I have a game where there are different categories to play with. These categories are basically plist files. So, if in the future, I want to add plists, the user should be able to download a plist and play new levels. So what I am aiming for is:
Download .plist from URL
Save .plist file in documents directory on iphone (forever)
use .plist
Here is what I did and it works (console logs "finished !!"), but if I check whether the file is in the documents directory, there is no response (the boolean fileExists stays NO).
-(void)startGame:(id)sender{
NSArray *categoriesArray = [[GameStateSingleton sharedMySingleton] categoriesArray];
NSString *category = [NSString stringWithFormat:[categoriesArray objectAtIndex:[sender tag]]];
NSString *thePath = [mainPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",category]];
NSDictionary *categoryPlist = [NSDictionary dictionaryWithContentsOfFile:thePath];
if(categoryPlist != nil){
[[GameStateSingleton sharedMySingleton]setCurrentCategory:category];
[[GameStateSingleton sharedMySingleton]updateHexCountAndInitalTime];
[[CCDirector sharedDirector]replaceScene:[CCTransitionFade transitionWithDuration:TRANSITIONDURATION scene:[LevelSets scene]]];
}
else{
[self plistForCategory:category];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *myCategory= [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",category]];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myCategory];
if(fileExists == YES){
[[GameStateSingleton sharedMySingleton]setCurrentCategory:category];
[[GameStateSingleton sharedMySingleton]updateHexCountAndInitalTime];
[[CCDirector sharedDirector]replaceScene:[CCTransitionFade transitionWithDuration:TRANSITIONDURATION scene:[LevelSets scene]]];
NSLog(#"category exists now");
}
}
}
-(void)plistForCategory:(NSString*)category
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSURL *url = [NSURL URLWithString:[ NSString stringWithFormat:#"http://www.tinycles.com/wannaplay/plists/%#.plist",category]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:documentsDirectory];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"finished !!");
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
// Download failed. This is why.
NSError *error = [request error];
NSLog(#"%#", error);
}
Maybe the problem is because you're starting an async request, so if the request has not finished, your if(fileExist==YES) still returns NO; i suggest you in this case to start a sync request:
- (IBAction)startRequest:(id)sender
{
NSURL *url = [NSURL URLWithString:LINK_TO_PLIST];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:DOC_PATH];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
//start your game after the file is downloaded
}
}
Related
Trying to write a method for my iPhone program that given a URL address to a file, it would download to the iOS App's Documents Directory.
Following AFNetowrking's Documentation, it seems to work fine except that the filename is always some garbage.
I'm using Xcode 5 with AFNetworking 2.0 added to my project. Here's the code that I have so far:
//#import "AFURLSessionManager.h"
//On load (or wherever):
[self downloadFile:#"http://www.irs.gov/pub/irs-pdf/fw4.pdf"];
-(void)downloadFile:(NSString *)UrlAddress
{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:UrlAddress];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
}
completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
NSLog(#"File downloaded to: %#", filePath);
}];
[downloadTask resume];
}
The end result is that the file is successfully downloaded to my documents directory, but with a garbled name:
File downloaded to: file:///Users/myname/Library/Application%20Support/iPhone%20Simulator/7.0/Applications/25188DCA-4277-488E-B08A-4BEC83E59194/Documents/CFNetworkDownload_60NWIf.tmp
The end result I'm expecting:
File downloaded to: file:///Users/myname/Library/Application%20Support/iPhone%20Simulator/7.0/Applications/25188DCA-4277-488E-B08A-4BEC83E59194/Documents/fw4.pdf
I used cocoapods to add AFNetworking to my project:
pod 'AFNetworking', "~> 2.0"
Lastly, what do I need to do to get the progress of the download?
This is the answer I was able to create:
-(void)downloadFile:(NSString *)UrlAddress
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:UrlAddress]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSString *pdfName = #"The_PDF_Name_I_Want.pdf";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:pdfName];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"Download = %f", (float)totalBytesRead / totalBytesExpectedToRead);
}];
[operation start];
}
I am open to improvements or suggestions :)
Simply you can replace this line:
return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
with:
return [documentsDirectoryPath URLByAppendingPathComponent:#"fw4.pdf"];
since [targetPath lastPathComponent] returns something like CFNetworkDownload_60NWIf.tmp
I am trying to read text file downloaded from my server.
-(void)downloadFile
{
NSURLRequest request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://myserver.com/website/file.txt"]];
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"file.txt"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
[operation setCompletionBlock:^{
NSLog(#"downloadComplete!");
NSString *path;
path = [[NSBundle mainBundle] pathForResource: #"file" ofType: #"txt"];
NSString *data = [self readFile: path];
NSLog(#"%#",data);
}];
[operation start];
}
-(NSString *)readFile:(NSString *)fileName
{
NSLog(#"readFile");
NSString *appFile = fileName;
NSFileManager *fileManager=[NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:appFile])
{
NSError *error= NULL;
NSString *resultData = [NSString stringWithContentsOfFile: appFile encoding: NSUTF8StringEncoding error: &error];
if (error == NULL)
return resultData;
}
return NULL;
}
It downloads the file successfully but I can't read file. Returns null. Probably I can't set file path correctly. I want to read file from device disk, not project bundle.
Change
path = [[NSBundle mainBundle] pathForResource: #"file" ofType: #"txt"];
to
path = filePath;
I made your stuff work, i dont know if you still need it
-(void)downloadFile
{
CNMRouter *routext;
routext = ((LDAppDelegate *)[UIApplication sharedApplication].delegate).router;
[[[Singleton sharedClient]httpClient] setParameterEncoding:AFFormURLParameterEncoding];
NSMutableURLRequest *request;
if([routext postOrGet]){
request = [[[Singleton sharedClient]httpClient] requestWithMethod:#"GET"
path:[routext getLoginURLPath:#"admin" andPassword:#"admin"]
parameters:nil];
}else{
request = [[[Singleton sharedClient]httpClient] requestWithMethod:#"POST"
path:[routext getBackupUrl]
parameters:[routext getBackupURLPath]];
}
// NSURLRequest request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://myserver.com/website/file.txt"]];
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlock:^{
NSLog(#"downloadComplete!");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"%#", [paths objectAtIndex:0]);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"file.txt"];
// operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
NSString *path;
// path = [[NSBundle mainBundle] pathForResource: #"file" ofType: #"txt"];
path = filePath;
NSString *data = [self readFile: path];
NSLog(#"%#",data);
}];
[operation start];
}
I moved some stuf from its place but basicaly you were trying to get your file before it was even downloaded so i just put some stuff inside the succes block. Its working for me, thank you!
I am uploading multiple images data using ASIHTTP request method. All Images uploaded successfully but for only last image ASIHttp request goes fail. I tried a lot but i can't get anymore.
Can someone help me?
My code is as follow:
for(int i=0;i<[arySteps count];i++)
{
NSMutableArray *StepDetail=[[NSMutableArray alloc] initWithArray:[DatabaseAccess getAddSteps:str]];
if([[[StepDetail objectAtIndex:0] valueForKey:#"s_image"] length]!=0)
{
NSMutableArray *imgary=[[[[StepDetail objectAtIndex:0] valueForKey:#"s_image"] componentsSeparatedByString:#","] mutableCopy];
imagedata1=[[NSData alloc] init];
imagedata2=[[NSData alloc] init];
imagedata3=[[NSData alloc] init];
for (int i=0; i<[imgary count]; i++)
{
if(i==0)
{
NSString *filename=[NSString stringWithFormat:#"%#.jpeg",[imgary objectAtIndex:0]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *movieURL = [NSURL fileURLWithPath:filePath];
imagedata1=[NSData dataWithContentsOfURL:movieURL];
NSLog(#"%#",imagedata1);
}
else if(i==1)
{
NSString *filename=[NSString stringWithFormat:#"%#.jpeg",[imgary objectAtIndex:1]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *movieURL = [NSURL fileURLWithPath:filePath];
imagedata2=[NSData dataWithContentsOfURL:movieURL];
NSLog(#"%#",imagedata2);
}
else if(i==2)
{
NSString *filename=[NSString stringWithFormat:#"%#.jpeg",[imgary objectAtIndex:2]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *movieURL = [NSURL fileURLWithPath:filePath];
imagedata3=[NSData dataWithContentsOfURL:movieURL];
NSLog(#"%#",imagedata3);
}
}
NSString *strurl=[NSString stringWithFormat:#"http://inst.niftysol.com/app/webroot/webservices/test.php?said=%d&stepid=%#", appdel.idPARENTID,s_id_live];
[self setHttprequest:[ASIFormDataRequest requestWithURL:[NSURL URLWithString:strurl]]];
//NSString *userid=[NSString stringWithFormat:#"%d",appdel.idUID];
// [httprequest setPostValue:userid forKey:#"s_user_id"];
[httprequest setShouldContinueWhenAppEntersBackground:YES];
[httprequest setDelegate:self];
[httprequest setDidFinishSelector:#selector(uploadFinished:)];
[httprequest setDidFailSelector:#selector(uploadFailed:)];
[httprequest setData:imagedata1 withFileName:#"1.jpeg" andContentType:#"image/jpeg" forKey:#"userfile1"];
[httprequest setData:imagedata2 withFileName:#"2.jpeg" andContentType:#"image/jpeg" forKey:#"userfile2"];
[httprequest setData:imagedata3 withFileName:#"3.jpeg" andContentType:#"image/jpeg" forKey:#"userfile3"];
countupload=countupload+1;
[httprequest startAsynchronous];
}
}
In above code I've got all images data properly but for last image request goes fail. I get the error:
Error Domain=ASIHTTPRequestErrorDomain Code=4 "The request was cancelled" UserInfo=0x96fbfe0 {NSLocalizedDescription=The request was cancelled}
You should switch to AFNetworking if possible, very easy to integrate. Though answer your question you should switch to network queue for ASIHTTPRequest.
Declare ASINetworkQueue *networkQueue; in header file, declare property #property (retain) ASINetworkQueue *networkQueue; and synthesize it as well in implementation file.
-(void)doUploadOperation //You can call this method for your upload operation.
{
[[self networkQueue] cancelAllOperations];
// Creating a new queue each time we use it means we don't have to worry about clearing delegates or resetting progress tracking
[self setNetworkQueue:[ASINetworkQueue queue]];
[[self networkQueue] setDelegate:self];
[[self networkQueue] setRequestDidFinishSelector:#selector(requestFinished:)];
[[self networkQueue] setRequestDidFailSelector:#selector(requestFailed:)];
[[self networkQueue] setQueueDidFinishSelector:#selector(queueFinished:)];
int i;
for (i=0; i<[arySteps count]; i++)
{
//First create image data
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filename=[NSString stringWithFormat:#"%#.jpeg",[imgary objectAtIndex:i]];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *movieURL = [NSURL fileURLWithPath:filePath];
NSData *imagedata=[NSData dataWithContentsOfURL:movieURL];
//Create request and add to network queue
NSString *strurl=[NSString stringWithFormat:#"http://inst.niftysol.com/app/webroot/webservices/test.php?said=%d&stepid=%#", appdel.idPARENTID,s_id_live];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:strurl]];
[request setShouldContinueWhenAppEntersBackground:YES];
[request setData:imagedata withFileName:[NSString stringWithFormat:#"%d.jpeg",i+1] andContentType:#"image/jpeg" forKey:[NSString stringWithFormat:#"userfile%d",i+1]];
request.tag = i;
[[self networkQueue] addOperation:request];
}
[[self networkQueue] go];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
if ([[self networkQueue] requestsCount] == 0) {
[self setNetworkQueue:nil];
}
//... Handle success
NSLog(#"Individual Request finished");
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
if ([[self networkQueue] requestsCount] == 0) {
[self setNetworkQueue:nil];
}
NSLog(#"Individual Request failed");
}
- (void)queueFinished:(ASINetworkQueue *)queue
{
if ([[self networkQueue] requestsCount] == 0) {
[self setNetworkQueue:nil];
}
NSLog(#"Whole Queue finished");
}
Hope this helps. Don't hesitate to message if you need more help.
I try to download a file from my server, this is the code, on my console I see the xml file, but I can't save it.
Where is the problem for you?
- (IBAction)grabURL:(id)sender{
NSURL *url = [NSURL URLWithString:#"http://www.endurodoc.net/photo/data.xml"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSString *response = [request responseString];
NSLog(#"%#",response);
}
else{
NSLog(#"Errore");
}
//[request setDownloadDestinationPath:#"/Users/kikko/Desktop/data.xml"];
// SAVED PDF PATH
// Get the Document directory
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// Add your filename to the directory to create your saved pdf location
NSString *pdfLocation = [documentDirectory stringByAppendingPathComponent:#"data.xml"];
// TEMPORARY PDF PATH
// Get the Caches directory
NSString *cachesDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// Add your filename to the directory to create your temp pdf location
NSString *tempPdfLocation = [cachesDirectory stringByAppendingPathComponent:#"data.xml"];
// Tell ASIHTTPRequest where to save things:
[request setTemporaryFileDownloadPath:tempPdfLocation];
[request setDownloadDestinationPath:pdfLocation];
}
You need to put:
[request setTemporaryFileDownloadPath:tempPdfLocation];
[request setDownloadDestinationPath:pdfLocation];
before:
[request startSynchronous];
ASIHTTPRequest does the file saving when the request is made, so if you set those properties after the request has already happened then nothing will happen.
i am fetching around 1500 image url and want to store these images in the document directory of iphone at one go??
please suggest any approach to do it...
thanks
Method to download all URLs and write into one file:
- (BOOL) downloadFilefromCDN :(NSString*)filename {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://example.com/getlinks.php"]]];
[request setHTTPMethod:#"GET"];
NSError *err = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
if (err != nil) { return FALSE; } // Download error
NSArray *searchPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[searchPath objectAtIndex:0] stringByAppendingString:[NSString stringWithFormat:#"/%#",filename]];
if ([data writeToFile:path atomically:YES] != FALSE) {
return TRUE;
} else {
return FALSE; // Error
}
}
You need to write a script that returns an answer including the 1400 links so you can write it into that file.
Method to download all images given by a NSArray* to document directory.
- (id) downloadFilefromCDN :(NSString*)filename {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://example.com/%#",filename]]];
[request setHTTPMethod:#"GET"];
NSError *err = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
if (err != nil) { return FALSE; }
return data;
}
- (NSArray*) downloadFilesfromCDN :(NSArray*)filenames {
NSMutableArray *mfiles = [[NSMutableArray alloc] init];
BOOL error = FALSE;
for (NSString* filename in filenames) {
NSArray *searchPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[searchPath objectAtIndex:0] stringByAppendingString:[NSString stringWithFormat:#"/%#",filename]];
id file = [self downloadFilefromCDN:filename];
if ([file isKindOfClass:[NSData class]]) {
if ([(NSData*)file writeToFile:path atomically:YES] != FALSE) {
[mfiles addObject:path];
} else {
error = TRUE; // Writing of file failed
}
} else {
error = TRUE; // Download failed
}
}
if (error) {
// Handle error
}
[filenames release];
return [NSArray arrayWithArray:mfiles];
}
Note: You need to read the pure filenames into a NSArray. If you have different origins change
[NSString stringWithFormat:#"http://example.com/%#",filename]
to
[NSString stringWithFormat:#"%#",filename]
and read the full paths (http://example.com/file1.png,http://example.com/file2.png) into a NSArray.
Done. Hope it will help.
Sorry for so much editing :S