File doesn't show in documents directory? - iphone

I want do download a PDF to my documents directory.
I do it like this:
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://www.test.com/test.pdf"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:[self documentsDirectory]];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"requestFinished");
NSError *error;
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self documentsDirectory] error:&error];
if (array == nil) {
NSLog(#"array == nil");
}
NSLog(#"Array count: %d", [array count]);
}
- (NSString *)documentsDirectory {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
return [paths objectAtIndex:0];
}
But my array is always empty, I don't know why...
It works now, made a new project and it works.
A bit weird.

This is happening because the code as written is actually replacing the Documents directory with your file instead of putting it in the Documents directory.
If you look in the Simulator directory in the Finder (~/Library/Application Support/iPhone Simulator/4.3/Applications/...), you'll see something like this:
Notice how the "Kind" of the Documents directory is no longer a "Folder" but a "Document" after your download completes.
If you append .pdf to the Documents file in the Finder, it should be your downloaded PDF. I tried your code and that's what it did for me. You are overwriting the Documents directory with your download.
Your code will work if you add an explicit file name to the download path. So something like this:
NSString *filePath = [[[self documentsDirectory] stringByAppendingPathComponent:#"localFile"] stringByAppendingPathExtension:#"pdf"]];
[request setDownloadDestinationPath:filePath];
If you check out the example in the HTTPRequest documentation, you'll see that a file path is specified, and not just a download directory.
As a side note, you should also implement the - (void)requestFailed:(ASIHTTPRequest *)request delegate method and check/print out the NSError when the contentsOfDirectoryAtPath: array is nil (in your requestFinished: code). That would have made it easier for you to track down the issue.
NOTE: Make sure to delete the app from your simulator before you fix your code, or you'll get an error when you try to write to that Documents directory, as it's now no longer a directory!

I'm not sure where your dir variable is coming from but it looks like this is where your problem lies.
You can return the array correctly like so:
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self documentsDirectory] error:&error];
From what i can tell your logging the array correctly before you assign it to *array but then you are using the dir variable. There is also no need to alloc a FileManger object as you can simply use [NSFileManger defaultManager] as you have done when assigning *array.
Also, when you say your array is empty, do you mean nil and your array == nil log is firing, or that you are using [array count]; and it is returning 0?

Related

Unique way to upload and download any kind of files to application sandbox

1) I want to download the data of any kind like the files of type .text, .png, .jpg, .docx, .xls, .pdf, .mp4, or whatever be the kind of files, Then i want to save it to the application sandboxs document directorys any of the sub directories that i have created under document directory of application sandbox.
2) Again whenever the user want to upload the files saved in the subdirectories of the application sandboxs document directory, The user will be able to browse through the data in the different directories of application sandboxs document directory, For that i have listed the data in the subdirectories of document directory of application sandbox in UITableView so that the user should be able to choose any of the file from the particular directory.
Problems/ things where i have stucked
I am using ASIHttpRequest for the upload and download , Where
1) For first need , means for downloading data i am using the methods -(void)grabURLInBackground to download the data from web and if its downloaded successfully then in the method -(void)requestFinished:(ASIHTTPRequest *)request i am saving that data to the subdirectory of the document directory of application sandbox with the particular name. The working code is below
-(void)grabURLInBackground
{
NSURL *url = [NSURL URLWithString:#"http://wordpress.org/plugins/about/readme.txt"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
-(void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
NSLog(#"responseString:%#",responseString);
UIAlertView *alt = [[UIAlertView alloc] initWithTitle:#"Download Status" message:#"Download finished" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alt show];
//Use when fetching binary data
//NSData *responseData = [request responseData];
//NSLog(#"responseData:%#",responseData);
//For storing the data to the subdirectory of the document directory named Doc the following code is used.
NSArray *paths;
NSString *documentsDirectory,*docDirectoryPath,*docFilePath;
//NSString *imageCachePath,*imageDicPath;
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSLog(#"documentsDirectory:%#",documentsDirectory);
docDirectoryPath = [documentsDirectory stringByAppendingPathComponent:#"/Docs"];
NSLog(#"docDirectoryPath:%#",docDirectoryPath);
docFilePath = [docDirectoryPath stringByAppendingPathComponent:#"textFileTwo"];
NSLog(#"docFilePath:%#",docFilePath);
if (![[NSFileManager defaultManager] fileExistsAtPath:docFilePath])
[[NSFileManager defaultManager] createFileAtPath:docFilePath
contents:[NSData dataWithContentsOfFile:responseString]
attributes:nil];
//************************************//
Here what i want after the download finishes we have the two option the way to fetch the text data and the way to fetch the binary data, Thats what is the thing , Here in my case the data will be of any kind, And i want to save that to particular directory, I will save it on my own but i want the Unique way to fetch the any kind of data and to save it to particular directory .
//************************************//
}
-(void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
NSLog(#"error:%#",error);
}
2) For the 2nd need means for the uploading data to any URL m using the same ASIHttpRequest like
-(void)uploadData {
//Suppose i want to upload the file that i have juz downloaded by the download code above.
// i fetched the path of the file i just saved with download code above, See the code below.
NSArray *paths;
NSString *documentsDirectory,*docDirectoryPath,*docFilePath;
//NSString *imageCachePath,*imageDicPath;
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSLog(#"documentsDirectory:%#",documentsDirectory);
docDirectoryPath = [documentsDirectory stringByAppendingPathComponent:#"/Docs"];
NSLog(#"docDirectoryPath:%#",docDirectoryPath);
docFilePath = [docDirectoryPath stringByAppendingPathComponent:#"textFileTwo"];
NSLog(#"docFilePath:%#",docFilePath);
// Upload Code
NSString *strURL = #"http://192.168.1.201/MyLegalNetMobile/MyLegalNetService.svc/FileUpload";
ASIFormDataRequest *uploadRequest = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:strURL]]; // Upload a file on disk
// Upload image data using asihttprequest
//UIImage *tempImg=[UIImage imageWithContentsOfFile:[NSString stringWithContentsOfURL:[NSURL URLWithString:imageCachePath] encoding:NSUTF8StringEncoding error:nil]];
//NSData *imageData1=UIImageJPEGRepresentation(tempImg, 1.0);
NSString *fetchedDataOfTxtFiles = [NSString stringWithContentsOfURL:[NSURL URLWithString:docFilePath] encoding:NSUTF8StringEncoding error:nil];
NSData *textData = [NSData dataWithContentsOfFile:fetchedDataOfTxtFiles];
NSLog(#"fetchedDataOfTxtFiles:%#",fetchedDataOfTxtFiles);
NSLog(#"textData:%#",textData);
[uploadRequest setData:textData withFileName:#"textFileTrialThree" andContentType:#"txt" forKey:#"txtData"];
[uploadRequest setRequestMethod:#"POST"];
[uploadRequest setDelegate:self];
[uploadRequest setTimeOutSeconds:10.0];
uploadRequest.shouldAttemptPersistentConnection = NO;
[uploadRequest setDidFinishSelector:#selector(uploadRequestFinished:)];
[uploadRequest setDidFailSelector:#selector(uploadRequestFailed:)];
[uploadRequest startAsynchronous];
//************************************//
Here again i have the different ways to upload the different kind of data, like for uploading the text data, different, ways is there same for the pdf, and image data is also, here i want the unique way to upload any kind of data to server, Also here I tried the image data uploading and text data uploading , Means i uploaded the files that i download from the any url. At the time of saving that downloaded files i converted them to NSData and saved to particular path of application sandboxs belonging directories. So while uploading again i got that path and for image data i converted the nsdata to uiimage , for the text file i only gave the path of file and uploaded the fiels to somewhere , The Files get uploaded on server, but there size was 0 bytes only, and the formate was different.
//************************************//
}
-(void)uploadRequestFinished:(ASIHTTPRequest *)request
{
NSString *responseString = [request responseString];
NSLog(#"Upload response %#", responseString);
}
-(void)uploadRequestFailed:(ASIHTTPRequest *)request{
NSLog(#" Error - Statistics file upload failed: \"%#\"",[[request error] localizedDescription]);
}
// Exact Problem.
/*
Any data that we download from the web using ASIHttpRequest before saving it to any path to application sandbox we convert some kind of data to NSData, And it get saved .
On the click of Browse button i have populated the data from different different subdirectories of the Document directory of the application sandbox in the UITableView, So I want to show the names of files with their extensions means with type that files were downloaded [as we save all data with converting to NSData it get saved with the names we give while saving only].
And then the time comes for the users to upload that data to any of the URL at that time also the files should get stored with their original formates means with which we downloaded the, */
To get list of files in directory try
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error
To get file extension take a look on responce headers. They can contain ContentType which was downloaded.
why not use the request property called downloadDestinationPath?? If you use it, you don´t need to do anything in RequestFinished method because the ASIHTTPRequest library keeps the type of the files what you have downloaded.
The request finished method is always for doing something with the data you have downloaded, as parsing an html file for remove the html headers. If you don´t want to modify the file that you are downloading you should use this method for show download status only.
Edit the download path before start the request:
NSArray *paths;
NSString *documentsDirectory,*docDirectoryPath,*docFilePath;
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
docDirectoryPath = [documentsDirectory stringByAppendingPathComponent:#"Docs"];// Remove the "/" from the string paths because you are using "stringByAppendingPathComponent"
docFilePath = [docDirectoryPath stringByAppendingPathComponent:#"textFileTwo"];
request = [ASIHTTPRequest requestWithURL:YOUR URL];
[request setDownloadDestinationPath:docFilePath];
[request startAsynchronous];
To list the content:
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error2];
for (int i = 0; i<[directoryContent count]; i++){
NSLog(#"content == %d", [directoryContent objectAtIndex:i];
}

Not able to write into text file

I need to write a string into a file. For that, my code is:
-(void)writeToFile:(NSString *)fileName: (NSString *)data {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// the path to write file
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];
[data writeToFile:appFile atomically:YES];
}
I am calling this method like this
ownServices *obj = [[ownServices alloc]init];
[obj writeToFile:#"iphone.txt" :#"this is mahesh babu"];
but it didn't write into the text file.
What's the reason? Can anyone please help me.
Thank u in advance.
The most likely problem is that the documents directory does not exist. Create it if it doesn't, then write to it:
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *parentDir = [paths objectAtIndex:0];
/* Create the parent directory.
* This is expected to fail if the directory already exists. */
(void)[[NSFileManager defaultManager]
createDirectoryAtPath:parentDir
withIntermediateDirectories:YES
attributes:nil error:NULL];
NSString *path = [parentDir stringByAppendingPathComponent:fileName];
/* Now write, and if it fails, you'll know why thanks to the |error| arg. */
NSError *error = nil;
BOOL ok = [data writeToFile:path options:NSDataWritingAtomic error:&error];
if (!ok) {
NSLog(#"%s: Failed to write to %#: %#", __func__, path, error);
}
Even simpler would be to use the latest API, which will create the directory for you if it doesn't already exist:
NSError *error = nil;
NSURL *parentURL = [[NSFileManager defaultManager]
URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask
appropriateForURL:nil create:YES error:&error];
if (!parentURL) {
NSLog(#"%s: *** Failed to get documents directory: %#", __func__, error):
return;
}
NSURL *furl = [parentURL URLByAppendingPathComponent:fileName];
error = nil;
BOOL ok = [data writeToURL:furl options:NSDataWritingAtomic error:&error];
if (!ok) {
NSLog(#"%s: *** Failed to write to %#: %#", __func__, furl, error);
}
Firstly, you are calling your method strangely. Rename the method to
-(void)writeString:(NSString *) data toFile:(NSString *)fileName
and call it like so:
[obj writeString:#"this is mahesh babu" toFile:#"iphone.txt"];
Secondly, writeToFile:atomically: is deprecated, use writeToFile:atomically:encoding:error::
NSError *error = nil;
BOOL success = [data writeToFile:appFile atomically:YES encoding:NSUTF8Encoding error:&error];
if (!success) {
NSLog(#"Error: %#", [error userInfo]);
}
This way, you also see what the error is.
Your code looks OK. Use the debugger (or an NSLog statement) to verify the values of data and appFile. If data is nil, nothing will happen (including no errors) because sending a message to nil is a no-op. It's also possible that appFile is not the path you think it is.
Check the permissions of the directory you are trying to write to (ls -la). On the device you can't, but on the simulator you can. Is it read-only for you? Is it owned by another user?
Assuming that isn't the problem, try calling with atomically:NO. Atomic file writing is performed by writing a file, then renaming it to replace the old one. If the problem is there, that will isolate the problem.
Bonus Style Critique
Class names should start with an uppercase letter: OwnServices instead of ownServices
Although your method name is perfectly valid, it's unusual to have two parameters with no words to separate them. A name like writeToFile:string: would be better.
Don't name a variable data if it is meant to point to an instance of something other than NSData. It's confusing, and there's almost a better (more specific) word you can use beside "data".

iPhone - properties of a file [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
iPhone - file properties
Hi all. i m creating an application which makes the iphone work as a pendrive for easy file sharing purpose.
In the first stage, i have some files(png, pdf, jpg, zip) in a directory and i made them display in the tableview in the form of mutable array without the extensions of each file.
In the second stage i have a detailedViewController which then displays the detailed view of the files like
file size
file type
if it is a image, it should open in imageView
if it is a song, it should play it
So i need to retrieve the properties like filePath, fileType, fileSize.. of each files. Now i got stuck in getting those properties like fileSize and fileType... Please help me proceed with a sample source code.
Here is my code.
- (void)listFiles {
NSFileManager *fm =[NSFileManager defaultManager];
NSError *error = nil;
NSString *parentDirectory = #"/Users/akilan/Documents";
NSArray *paths = [fm contentsOfDirectoryAtPath:parentDirectory error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
error = nil;
}
directoryContent = [[NSMutableArray alloc] init];
for (NSString *path in paths){
documentsDirectory = [[path lastPathComponent] stringByDeletingPathExtension];
NSLog(#"%#", documentsDirectory);
[directoryContent addObject:documentsDirectory];
}
Thanks in advance..
you should use the method attributesOfItemAtPath:error: of your filemanager instance.
Have a look at the documentation.

Clear Absolute Cache on Application close Ipad app

I am saving Images in NSCachesDirectory in a App. At the end of app execution i would like to clear all temporary cache. Is there a way to force clear all cache on application exit. I do realise the local folder keeps cache for 3 days..but my requirement is to force clear the Cache. Thx
This code should do the trick, just substitute the name of your cache directory...
NSString *cacheDirectoryName = [self getCacheDirectoryName];
NSArray *items = [fileManager directoryContentsAtPath:cacheDirectoryName];
for (NSString *item in items)
{
NSString *path = [cacheDirectoryName stringByAppendingPathComponent:item];
NSError *error = nil;
[fileManager removeItemAtPath:path error:&error];
[error release];
}
Then call the code in your AppDelegate applicationWillTerminate method.

Core Data quesition

I'm trying to write two applications (iphone and desktop) to achieve what's been described in the following link:
core-data-is-it-possible-to-build-a-desktop-app-to-create-the-data-model-for-an
Ok. So I've created a very simple desktop app the has a single entity named Client with a string attribute field called name. I've also generated the corresponding Model class.
I've run the app added a couple of client names to the list and saved the file (as Testing.sqlite).
Now in my equivalent iphone app I'm attempting to load the file. I've generated the app initially using one of the application templates and included Core Data. NB: I've mirrored the Client entity and generated the corresponding Model class.
I've gone into my "application delegate" class and amended the persistentStoreCoordinator method to reference my "Testing.sqlite" file i.e.
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"Testing.sqlite"]];
I've also copied the saved desktop app file into the expected location i.e.
~/Library/Application Support/IPhone Simulator/User/... etc.
So now in theory at least each of the two apps should be the same.
However when I'm attempting to load the data from the it always seems to be empty. My code looks a little like this:
// fetch the delegate.
TestingAppDelegate *app = (TestingAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = [app managedObjectContext];
// construct the request.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Client" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// execute the request.
NSError *error;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
if (results == nil) {
// Handle the error.
NSLog(#"No data loaded");
}
NSLog(#"Returned: %#", results);
// finally release
[results release];
[request release];
I can't seem to figure out what's going wrong. Any tips or suggestions would be totally appreciated.
When I've looked at the instance of the persistanceStoreCoordinator, managedObjectContext, resulting array (NSArray) whilst debugging I can see that it seems to contain 0 records for all of these. So I'm confused.
NB: The Testing.sqlite file contains entries.
Thanks in advance,
Matt
Simply copying the sqlite database file will not work when using Core Data.
You need to fully replicate the persistent store you created in your desktop application.
However, this may be a problem related to the fact that Core Data is not seeing your database file even though you copied it. Try the following:
1) add your database file to your project in the resources group
2) use this method to actually copy your database file in place
- (NSString *) initialize_db {
NSString *DATABASE_RESOURCE_NAME = #"testing";
NSString *DATABASE_RESOURCE_TYPE = #"sqlite";
NSString *DATABASE_FILE_NAME = #"testing.sqlite";
// copy the database from the bundle if necessary
// look to see if DB is in known location (~/Documents/$DATABASE_FILE_NAME)
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolderPath = [searchPaths objectAtIndex: 0];
NSString *dbFilePath = [documentFolderPath stringByAppendingPathComponent: DATABASE_FILE_NAME];
[dbFilePath retain];
if (! [[NSFileManager defaultManager] fileExistsAtPath: dbFilePath]) {
// didn't find db, need to copy
NSString *backupDbPath = [[NSBundle mainBundle]
pathForResource:DATABASE_RESOURCE_NAME
ofType:DATABASE_RESOURCE_TYPE];
if (backupDbPath == nil) {
// couldn't find backup db to copy, bail
NSLog (#"couldn't init db");
return NULL;
} else {
BOOL copiedBackupDb = [[NSFileManager defaultManager]
copyItemAtPath:backupDbPath
toPath:dbFilePath
error:nil];
if (! copiedBackupDb) {
// copying backup db failed, bail
NSLog (#"couldn't init db");
return NULL;
}
}
}
return dbFilePath;
}
Once you have copied the database file, you have its file path returned, and you use it to actually open the database.