I wrote a quick objective-C method that uses Amazon's AWS iOS SDK to synchronously download a file from my Amazon S3 Bucket in my iPad app. This is an enterprise app, and I am using reachability to detect WiFi before allowing synchronization with S3. It is working fine for short downloads (those in kilobytes), but with files that are around 20-30 megs, it will continue to download into the stream and the file will continue growing. I've not let it go to see if it will eventually stop/crash, but I've watched a file that was 30 megs go past 90 megs in my iOS Simulator. I've read into several cold threads where some have experienced the same and I really need an answer.
Here is my method...
- (void)retrieveRemoteFile:(NSString *)fileName {
NSString *destinationFileName = [NSString stringWithFormat:@"%@%@",[self getBucketDirectory],fileName];
AmazonS3Client *s3 = [[[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY] autorelease];
NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:destinationFileName append:NO];
[stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[stream open];
S3GetObjectRequest *request = [[S3GetObjectRequest alloc] initWithKey:fileName withBucket:BUCKET];
request.outputStream = stream;
[s3 getObject:request];
[stream close];
[stream release];
[request release];
}
Re-evaluating the situation, I'd really like to get my method using an ASynchronous Request and use a S3RequestDelegate object to help me update the bytesIn as it's downloading. In their archive, there is a sample in S3AsyncViewController that should show how to do what I want. I've added S3RequestDelegate.h/.m into my project, and implemented a S3RequestDelegate in my .h like this...
#import "S3RequestDelegate.h"
... {
S3RequestDelegate *s3Delegate;
}
I've altered my retrieveRemoteFile method to look a little like this (it's changed all day and I haven't gotten anywhere)
- (void)retrieveRemoteFile:(NSString *)fileName {
NSString *destinationFileName = [NSString stringWithFormat:@"%@%@",[self getBucketDirectory],fileName];
AmazonS3Client *s3 = [[[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY] autorelease];
NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:destinationFileName append:NO];
//[stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//[stream open];
S3GetObjectRequest *request = [[S3GetObjectRequest alloc] initWithKey:fileName withBucket:BUCKET];
request.outputStream = stream;
s3Delegate = [[S3RequestDelegate alloc] init];
[request setDelegate:s3Delegate];
[s3 getObject:request];
//[stream close];
//[stream release];
//[request release];
}
As you can see, I've set the S3GetObjectRequest delegate with setDelegate to my S3RequestDelegate pointer s3Delegate. I've added breakpoints in all of the delegate methods of the S3RequestDelegate object, but none of them are executing. In looking for a received file on my simulator, nothing is even getting downloaded now.
The sample makes it look like all you need to do is set a delegate to make it asynchronous. It also makes it look like you don't need to manage the stream object, and whether you do or not, nothing gets downloaded. I'm setting the delegate and it's never running any of the delegate methods; didReceiveResponse, didCompleteWithResponse, didReceiveData, didSendData, totalBytesExpectedToWrite, didFailWithError or didFailWithServiceException.