As a Black Raccoon writer, I may be biased (well, I KNOW that I am biased), but I tried to make it as simple and powerful as possible. See what you want to do, upload the file:
There are four things we need to upload a file - run the code, then four delegate methods: rewrite validation, data, success and failure. Suppose you read the entire file in memory (good for small files less than 2 megabytes).
First you need this in the header:
BRRequestUpload *uploadData; // Black Raccoon upload object NSData *uploadData; // data we plan to upload
Now for the piece of code:
- (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 ask for 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; } }
Then Black Raccoon will ask you to send pieces of data. If you have a very large file, you NEVER want to try to send it in one shot - the Apple API will strangle and delete the data. However, we only have one small piece, 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 that we can ONLY do this for a small file.
Next, we have our completion handler (if everything works according to plan):
-(void) requestCompleted: (BRRequest *) request { if (request == uploadFile) { NSLog(@"%@ completed!", request); uploadFile = nil; } }
Finally, we have our error handler:
-(void) requestFailed:(BRRequest *) request { if (request == uploadFile) { NSLog(@"%@", request.error.message); uploadFile = nil; } }
It would be WONDERFUL if it were as simple as saying [BRFtpUploadTo: dest srcfile: srcFile destfile: dstFile] , but there are many reasons why you DO NOT. This is partly due to how Apple implemented its internal FTP. There are also problems with blocking, errors, etc. After all, FTP sounds like it should be trivial, but ultimately it's a bit of a nightmare.
FTP is non-trivial, so there are so many implementations. I do not claim that Black Raccoon is the best, but it is supported with answers to questions ranging from a few minutes to several days.
It may seem complicated at first, but Black Raccoon, in my opinion, is one of the best FTP libraries. I spent a lot of time and effort to make it a quality product with an excellent answer to problems. How can I do this for free? Volume .;)
Good luck with any FTP software you end up with!