Search code examples
objective-camazon-s3plistafnetworking-2

Corrupted files downloaded from Amazon S3 using AFAmazonS3Client


I created an app that download a plist file from Amazon S3. I was using AFAmazonS3Client a client based in AFNetworking framework.

-(void) getFile:(NSString *)fileName{
    self.s3Manager = [[AFAmazonS3Manager alloc] initWithAccessKeyID:@"..." secret:@"..."];
    self.s3Manager.requestSerializer.region = AFAmazonS3SAEast1Region;
    self.s3Manager.requestSerializer.bucket = @"verba";

    NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    documentsPath = [documentsPath stringByAppendingPathComponent:fileName];

    NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:documentsPath append:NO];

    [self.s3Manager getObjectWithPath:@""
                         outputStream:stream
                             progress:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
         NSLog(@"%f%% Downloaded", (totalBytesRead / (totalBytesExpectedToRead * 1.0f) * 100));
    } success:^(id responseObject) {
         NSLog(@"Download Complete");
    } failure:^(NSError *error) {
        NSLog(@"Error: %@", error);
    }];
}

Then I checked if the plist file was in document folder. And it was. So I tried to open plist file and the result was nil:

-(NSString*) loadListName:(NSString*)fileName{
    NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString* filePath = [documentsPath stringByAppendingPathComponent:fileName];

    NSDictionary *temp;
    if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]){
        temp = [NSDictionary dictionaryWithContentsOfFile:filePath];
    } else {
        NSLog(@"File not found.");
    }

    NSString *listName = [temp objectForKey:@"name"];

    return listName;
}

So I tried to add plist file manually. I downloaded and copied it to the documents folder and then dictionaryWithContentsOfFile could open the file. So I suppose that plist file was corrupted when I download the file using AFAmazonS3Client.

What I am doing wrong ?

Update 1

I realize that every single file that I downloaded from S3 are corrupted. I don't know if I handle the NSOutputStream in the right way or maybe another stuff.


Solution

  • For some reason getObjectWithPath method from AFAmazonS3Manager is not working properly.

    So I rewrite my method using AFHTTPRequestOperation directly from AFNetworking

    - (void)downloadFile:(NSString *)fileName block:(void (^)(NSError *error))block {
    
        NSString *urlString = @"https://[bucket].[server area].amazonaws.com/";
        urlString = [urlString stringByAppendingPathComponent:fileName];
    
        NSURL *url = [NSURL URLWithString:urlString];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
        NSSet *set = operation.responseSerializer.acceptableContentTypes;
    
        if ([[fileName pathExtension] isEqualToString:@"m4a"]) {
            NSLog(@"%@ set as audio/mp4", fileName);
            operation.responseSerializer.acceptableContentTypes = [set setByAddingObject:@"audio/mp4"];
        } else if ([[fileName pathExtension] isEqualToString:@"png"]) {
            NSLog(@"%@ set as image/png", fileName);
            operation.responseSerializer.acceptableContentTypes = [set setByAddingObject:@"image/png"];
        } else if ([[fileName pathExtension] isEqualToString:@"plist"]) {
            NSLog(@"%@ set as application/x-plist", fileName);
            operation.responseSerializer.acceptableContentTypes = [set setByAddingObject:@"application/x-plist"];
        }
    
        NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    
        NSString *fullPath = [documentsPath stringByAppendingPathComponent:[url lastPathComponent]];
    
        [operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:fullPath append:NO]];
    
        [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
            NSLog(@"bytesRead: %lu, totalBytesRead: %lld, totalBytesExpectedToRead: %lld", (unsigned long)bytesRead, totalBytesRead, totalBytesExpectedToRead);
        }];
    
        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    
            if (block) {
                block(nil);
            }
    
            NSLog(@"RES: %@", [[[operation response] allHeaderFields] description]);
    
            NSError *error;
            NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:&error];
    
            if (error) {
                NSLog(@"ERR: %@", [error description]);
            } else {
                NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
                long long fileSize = [fileSizeNumber longLongValue];
    
                NSLog(@"%lld", fileSize);
            }
    
    
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            if (block) {
                block(error);
            }
            NSLog(@"ERR: %@", [error description]);
        }];
    
        [operation start];
    }