Not deleting file from ftp using CFURLDestroyResource method in iphone - ios

I have performed upload,download file from ftp using FTPHelper class. It's working perfectly.The issue generated in delete operation. While I'm deleting file from ftp server, nothing happens!. I don't know where I'm getting wrong. I have refered stackoverflow link to solve delete file from ftp but unable to do that.Below is my code to delete file from ftp.
pragma mark ***** Delete File From FTP
+(void)deleteFileFromFTPforItem:(NSString *) anItem
{
[sharedInstance deleteFileFromFTPforItem:anItem];
}
-(void)deleteFileFromFTPforItem:(NSString *) anItem
{
if (!self.uname || !self.pword) COMPLAIN_AND_BAIL(#"Please set user name and password first");
if (!self.urlString) COMPLAIN_AND_BAIL(#"Please set URL string first");
NSString *baseDeleteURL = [NSString stringWithFormat:#"%#/",self.urlString];
NSString *deleteFilePath = [baseDeleteURL stringByAppendingString:anItem];
CFURLRef deleteURL = (CFURLRef)[[NSURL alloc] initWithString:deleteFilePath];
//SInt32 *errorCode = NULL;
//CFURLDestroyResource(deleteURL, errorCode);
DeleteFile(deleteURL);
CFRelease(deleteURL);
}
static Boolean DeleteFile(CFURLRef urlToDelete)
{
Boolean success = true;
CFURLRef deleteURL = urlToDelete;
SInt32 *errorCode = NULL;
success = CFURLDestroyResource(deleteURL, errorCode);
return success;
}
Please give me a proper solution where am I going wrong.I have surfed lot of things but unable to get proper way to delete file from ftp.I have referred link to upload and download file to/from ftp.Your help would be appreciable.Thanks in advanced

To make a long story short, FTP support in NSURL and CFURL should be considered download-only. I don't think it ever fully worked, and ftp is thoroughly deprecated for any purposes other than anonymous downloads anyway, so it is unlikely to ever be fixed.
You can use other FTP access frameworks, as described in this question:
CFURLDestroyResource is now deprecated in iOS7. Anyone know what to use instead?
but really, you should probably be asking yourself whether using FTP is really the right way to do whatever you're trying to do, as opposed to (for example) WebDAV.

Related

Can I upload an MP3 file to my server from iOS?

I was googling this question but nothing useful or current came up. I'd like to know if (and if, how) you can select an MP3 file (from itunes?) and upload the contents to one of my own servers on iOS (iphone & ipad app).
One of my clients is asking me if it's possible to do this, and I havn't found the answer yet.
Thanks in advance!
The short answer would be YES.
Here is a working solution for me. But you need to use a third party library. Then this is what you need to do:
Create a temp folder either in the NSDocuments directory or a temp directory.
Use MPMediaQuery to load the music files.
The object that you will get from the MPMediaQuery is an MPMediaItem. With this you can get the asset URL of the media item.
Code:
NSString *assetURL = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
get the extension of with the asset URL
NSString *extension = [TSLibraryImport extensionForAssetURL:assetURL];
set a location URL (This will be the location where the mp3 music data will be imported).
NSString *locationURL = [[NSURL fileURLWithPath:[path stringByAppendingPathComponent:musicTitleYouWant]] URLByAppendingPathExtension:extension];
Now you can import the contents of the mp3 from to the directory you set earlier.
TSLibraryImport *libraryImport = [[TSLibraryImport alloc] init];
[libraryImport importAsset:assetURL toURL:locationURL completionBlock:^(TSLibraryImport *libraryImport)
{
if(libraryImport.status == AVAssetExportSessionStatusCompleted)
{
//Once complete the file will be store on the location URL you set earlier. Now you can get the file from that location and convert it to NSData and send it to the server. There are plenty of ways to do that.
}
else
{
//Here means import failed. :(
}
}];
Hope this helps. :)

How to read content from plain text remote file with objective-c

I want to read a list (in plain text) from a remote file line by line.
I have found some answers but they're not the ones I'm looking for.
p.s. I've been programing in objective-c and developing in iOS for about 2 months, I'm a rookie i might not understand or recognize some terms. Please answer like you are talking to a beginner.
If i am not wrong you just want to read a text from remote file, so here it is.
NSString * result = NULL;
NSError *err = nil;
NSURL * urlToRequest = [NSURL URLWithString:#"YOUR_REMOTE_FILE_URL"];//like "http://www.example.org/abc.txt"
if(urlToRequest)
{
result = [NSString stringWithContentsOfURL: urlToRequest
encoding:NSUTF8StringEncoding error:&err];
}
if(!err){
NSLog(#"Result::%#",result);
}
To load the remote txt file, you should take a look at NSURLConnection or AFNetworking (there are other possibilities, these two are probably the most common).
You will then get the content of the file. Depending on what you intend to do with it, you may have to parse it, either with something as simple as -[NSString componentsSeparatedByString:] or with something a bit more powerful like NSScanner.
There are three steps involved in loading a file
create the object that specifies the location of the file
call the appropriate NSString class method to load the file into a
string
handle the error if the file is not found
In step 1, you need to either create an NSString with the full path to the file in the file system, or you need to create an NSURL with the network location of the file. In the example below, the code creates an NSURL since your file is on the network.
In step 2, use the stringWithContentsOfFile method to load a file from the file system, or the stringWithContentsOfURL method to load a file from the network. In either case, you can specify the file encoding, or ask iOS to auto-detect the file encoding. The code below auto detects while loading from the network.
In step 3, the code below dumps the file to the debug console if successful or dumps the error object to the console on failure.
Missing from this code is multithreading. The code will block until the file is loaded. Running the code on a background thread, and properly notifying the main thread when the download is complete, is left as an exercise for the reader.
NSURL *url = [NSURL URLWithString:#"www.example.com/somefile.txt"];
NSStringEncoding encoding;
NSError *error;
NSString *str = [NSString stringWithContentsOfURL:url usedEncoding:&encoding error:&error];
if ( str )
NSLog( #"%#", str );
else
NSLog( #"%#", error );

Xcode - iOS - Simply upload a file to FTP Server

I'm trying to work with FTP Servers.
I have googled around for everything and everything is hard to understand for beginners like me. SimpleFTPSample is hard to understand because it is so much at a time. views, buttons, labels, textflelds, upload, download, request, list, get. Same with BlackRaccoon and everything else.
How to Simply and programily upload "test.txt" to FTP Server: "192.168.1.111" in Xcode (iPhone app) without views or button. Just code that can be in the ViewDidLoad for example.
Maybe something like this?:
NSURL* url = [NSURL URLWithString:#"ftp://username:pw#189.92.32.34"];
CFReadStreamRef stream = CFReadStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) url);
stream.delegate= self;
[stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[stream open];
but which file?
expand this, or write a new code. i don't know, this is new for me.
Thanks Jonathan
As the writer of Black Raccoon perhaps I'm biased (well, I KNOW I'm biased), but I've attempted to make it as simple and powerful as possible. Let's look at what you want to do, upload a file:
There are four things we need to upload a file - start up code, then four delegate methods: overwrite check, data, success and the fail. Let's assume that you read the entire file into memory (okay for small files less than 2 megs).
First, you need this in your header:
BRRequestUpload *uploadData; // Black Raccoon's upload object
NSData *uploadData; // data we plan to upload
Now for the code part:
- (IBAction) uploadFile :(id)sender
{
//----- get the file path for the item we want to upload
NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filepath = [NSString stringWithFormat: #"%#/%#", applicationDocumentsDir, #"file.text"];
//----- read the entire file into memory (small files only)
uploadData = [NSData dataWithContentsOfFile: filepath];
//----- create our upload object
uploadFile = [[BRRequestUpload alloc] initWithDelegate: self];
//----- for anonymous login just leave the username and password nil
uploadFile.path = #"/home/user/myfile.txt";
uploadFile.hostname = #"192.168.1.100";
uploadFile.username = #"yourusername";
uploadFile.password = #"yourpassword";
//----- we start the request
[uploadFile start];
}
The first will be asking your code if you want to overwrite an existing file.
-(BOOL) shouldOverwriteFileWithRequest: (BRRequest *) request
{
//----- set this as appropriate if you want the file to be overwritten
if (request == uploadFile)
{
//----- if uploading a file, we set it to YES (if set to NO, nothing happens)
return YES;
}
}
Next, Black Raccoon will ask you for chunks of data to send. If you have a very large file you NEVER want to try to send it all in one shot - Apple's API will choke and drop data. However, we only have one small chunk so we do this:
- (NSData *) requestDataToSend: (BRRequestUpload *) request
{
//----- returns data object or nil when complete
//----- basically, first time we return the pointer to the NSData.
//----- and BR will upload the data.
//----- Second time we return nil which means no more data to send
NSData *temp = uploadData; // this is a shallow copy of the pointer
uploadData = nil; // next time around, return nil...
return temp;
}
Remember we can ONLY do this for a small file.
Next we have our completion handler (if things worked according to plan):
-(void) requestCompleted: (BRRequest *) request
{
if (request == uploadFile)
{
NSLog(#"%# completed!", request);
uploadFile = nil;
}
}
Lastly we have our failure handler:
-(void) requestFailed:(BRRequest *) request
{
if (request == uploadFile)
{
NSLog(#"%#", request.error.message);
uploadFile = nil;
}
}
It would be WONDERFUL if it was as simple as saying [BRFtpUploadTo: dest srcfile: srcFile destfile: dstFile] but there are many reasons why you SHOULDN'T. Part of it has to do with how Apple has implemented their internal FTP. There are also the issues of blocking, errors, etc. In the end, FTP sounds like it should be trivial but ends up being a bit of a nightmare.
FTP is non-trivial which is why there are so many implementations. I'm not arguing that Black Raccoon is the best, but it is maintained with response to issues being between minutes to a couple of days.
It may look daunting at first, but Black Raccoon is, in my opinion, one of the better FTP libraries. I've spent a lot of time and effort to make it a quality product with excellent response to issues. How do I do this for free? Volume. ;)
Good luck with whatever FTP software you end up with!
Upload path is required when uploading. That is the way FTP works.
The port is the standard FTP port. I know of no way to change this without violating the API. If you figure it out, you stand a good chance of not passing Apple's check.
This code will upload/download any file.
I do not know how to make this work under secure conditions. This uses Apple's FTP protocol. There are other FTP packages that have built this from scratch and are far more intelligent. I would look into them.
BR was designed because I needed simple FTP communication. White Raccoon didn't do this for me because at the time (it has since been modernized).

NSFileWrapper fails when from iCloud and works from local directory

I have a problem syncing NSFileWrapper documents with iCloud. I am able to create my wrapper and save it to my ubiquitous container.
When I try to read it from the device that created it, it works. When I try to read form another device that got it from iCloud, it crashes.
Some code:
This function to add a wrapper container with a NSString
- (void) addNSString:(NSString*)_string toFileWrapper:(NSFileWrapper*)_wrapper forKey:(NSString*)_key {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_string];
if(data) {
[_wrapper addRegularFileWithContents:data preferredFilename:_key];
}
}
And then here is how I decode it:
- (id) unarchiveObjectFromWrappers:(NSDictionary*)_wrappers withKey:(NSString*)_key {
id value = nil;
NSFileWrapper *wrapper = [_wrappers valueForKey:_key];
if(wrapper) {
NSData *data = [wrapper regularFileContents];
if(data) {
value = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
}
return value;
}
The decoding part works on one device and not on the others (EXC_BAD_ACCESS when the NSKeyedUnarchiver tries to unarchive from the NSData. The NSData seems good, it has the proper length and everything but when I try to log its datas for example it crashes).
My guess is that the NSFileWrapper doesn't download its full content, only its structure and that I have to do something to make it available. But I don't know what.
Any ideas?
========
Edit:
NSURLUbiquitousItemIsDownloadedKey says that the file is downloaded BUT if I try to copy it to the sandbox it fails with this error: "The operation couldn’t be completed. Bad file descriptor"
So the file is either not uploaded properly to iCloud or not downloaded properly...
It drove me crazy too. The solution is rather simple, yet totally undocumented by Apple. You must download the file specifically. Only the file wrapper is downloaded automatically, but not its contents. That's why the check says the file exists.
Before copying the file over, call something like this:
[[NSFileManager defaultManager]startDownloadingUbiquitousItemAtURL:cloudURL error:nil];
Related: Cannot sync simple text file with iCloud (bad file descriptor)

Invalidating QLPreviewController "cache"

QLPreviewController seems to cache file contents based on the local file's URL. In my application, the file contents can be updated remotely and would cause the new contents to be downloaded.
If I view a file in QLPreviewController, update it remotely, then re-preview it, the file does not show up as updated.
The file is definitely updated on disk, and other controls show the correct updated file.
The workaround I'm using right now is to basically move a file when it's previewed to a unique filename (using timestamp), which will of course not be in the QLPreviewController's cache. However, this has other repercussions, for example, if the app is killed or it crashes (god forbid), I won't know "where" to find the downloaded file.
I'm looking for less invasive hacks, or solutions to making QLPreviewController refresh its cache. The APIs don't seem to expose anything, so don't be afraid to submit a hack if it's less gross than the one I've presented above (not including copying/moving the file to a guaranteed unique URL, which I am already utilizing).
Just ran into this issue myself. I solved it by recreating the QLPreviewController each time I reload an item with the same name as the currently viewed item. Creating a new QLPreviewController clears the cache.
I know this is an old question but someone might have the same problem and find this answer helpful.
You should use refreshCurrentPreviewItem after downloading complete
I had the same problem. Opening a locally generated CSV file.
I have my _previewController* setup as a #property of my controller. Then what i did:
- (void)viewDidLoad
{
[super viewDidLoad];
self.previewController = [[QLPreviewController alloc] init];
_previewController.delegate=self;
_previewController.dataSource=self;
}
- (void)previewCSV
{
[_previewController reloadData]; // this triggers a reload
[self presentModalViewController:_previewController animated:YES];
}
IN other solution that comes to mind (not tested).
Depending on your URL, you could add something like http://url?time=123456 to your URL. Like this you change the URL but without side effect. The time (or any other parameter) you can change on each request.
It's the ugliest bug in iOS. Cache management in iOS 5 and beyond. I think is the same reason that makes iCloud buggy, Share-at-Home crashing and so on. Bad cache managements and so worst synchronization systems.
Well, my solution for this was to store the download file in a folder and use the current date to name the folder. It is equivalent to #Rogier's solution, but this works always. You get a name for the folder, for example, with [[NSDate date] description]. Instead of saving the file replacing the old one, you delete previous file, delete previous folder and save new file in a new folder. It's working fine for me.
Just remove all files from tmp directory like this:
- (void)clearCache
{
NSString *tempPath = NSTemporaryDirectory();
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tempPath error:nil];
NSFileManager *fileManager = [NSFileManager defaultManager];
for (int i = 0; i < [dirContents count]; i++) {
NSLog(#"Directory Count: %i", [dirContents count]);
NSString *contentsOnly = [NSString stringWithFormat:#"%#%#", tempPath, [dirContents objectAtIndex:i]];
[fileManager removeItemAtPath:contentsOnly error:nil];
}
}

Resources