从Amazon S3 Bucket iOS下载多个项目

时间:2014-07-28 12:44:37

标签: ios amazon-web-services amazon-s3

我最近在我的应用程序中实现了新的AWS 2.0 iOS SDK(yay,cocoapods!),并使用亚马逊管理的示例代码来正确配置访问和下载。我可以毫无问题地成功下载单个项目,但我需要能够下载基于当前tableview动态生成的多个文件。似乎没有办法设置批量下载,因此我只是尝试遍历一组对象并触发每个对象的下载。它可以工作,但如果列表包含多个项目,它会随机开始失火。例如,如果我动态创建的列表中有14个项目,则将下载12个项目,而其他2个项目甚至未尝试过。请求消失了。在我的测试中,我添加了一个sleep(1)计时器,然后触发并下载了所有14个计时器,所以我猜测我压倒了下载请求,除非我放慢速度,否则它们会被丢弃。减慢它并不理想...也许还有另一种方式?这是代码:

 - (IBAction)downloadAllPics:(UIBarButtonItem *)sender {
if (debug==1) {
    NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));
}

CoreDataHelper *cdh =
[(AppDelegate *)[[UIApplication sharedApplication] delegate] cdh];

// for loop iterates through all of the items in the tableview
for (Item *item in self.frc.fetchedObjects) {

    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *downloadingFilePath1 = [NSString stringWithFormat:@"%@/%@@2x.jpg",docDir, item.imageName];
    NSURL *downloadingFileURL1 = [NSURL fileURLWithPath:downloadingFilePath1];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    if ([fileManager fileExistsAtPath:downloadingFilePath1]) {
        fileAlreadyExists = TRUE;
        if (![fileManager removeItemAtPath:downloadingFilePath1
                                     error:&error]) {
            NSLog(@"Error: %@", error);
        }
    }
    __weak typeof(self) weakSelf = self;

    self.downloadRequest1 = [AWSS3TransferManagerDownloadRequest new];
    self.downloadRequest1.bucket = S3BucketName;
    //  self.downloadRequest1.key = S3KeyDownloadName1;
    self.downloadRequest1.key = [NSString stringWithFormat:@"images/%@@2x.jpg", item.imageName];
    self.downloadRequest1.downloadingFileURL = downloadingFileURL1;
    self.downloadRequest1.downloadProgress = ^(int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite){
        // update progress
        dispatch_sync(dispatch_get_main_queue(), ^{
            weakSelf.file1AlreadyDownloaded = totalBytesWritten;
            weakSelf.file1Size = totalBytesExpectedToWrite;
        });

    };

     // this launches the actual S3 transfer manager - it is successfully launched with each pass of loop
    [self downloadFiles];
}

[cdh backgroundSaveContext];

 }

启动downloadFiles方法:

 - (void) downloadFiles {
//if I add this sleep, all 14 download. If I don't usually 11-13 download.
sleep(1);
AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];

__block int downloadCount = 0;

[[transferManager download:self.downloadRequest1] continueWithExecutor:[BFExecutor mainThreadExecutor] withBlock:^id(BFTask *task) {
     if (task.error != nil){
        if(task.error.code != AWSS3TransferManagerErrorCancelled && task.error.code != AWSS3TransferManagerErrorPaused){
            NSLog(@"%s Errorx: [%@]",__PRETTY_FUNCTION__, task.error);
        }
    } else {
        self.downloadRequest1 = nil;

    }
    return nil;
}];        
 }

必须有一种从Amazon S3存储桶下载动态文件列表的方法,对吧?也许有一个传输管理器允许一组文件而不是单独执行它们?

感谢任何和所有帮助。 扎克

2 个答案:

答案 0 :(得分:0)

听起来像请求超时间隔设置问题。

首先,配置AWSServiceConfiguration *configuration = ...时尝试配置timeoutIntervalForRequest属性。另外,maxRetryCount也是如此。如果下载每个操作失败,maxRetryCount将尝试下载。

AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:DefaultServiceRegionType
                                                                     credentialsProvider:credentialsProvider];
[configuration setMaxRetryCount:2]; // 10 is the max
[configuration setTimeoutIntervalForRequest:120]; // 120 seconds

其次,对于下载多个项目,尝试将每个AWSTask收集到一个数组中,并在组操作结束时获得结果。前)

// task collector
NSMutableSet *uniqueTasks = [NSMutableSet new];

// Loop
for (0 -> numOfDownloads) {
     AWSS3TransferManagerDownloadRequest *downloadRequest = [AWSS3TransferManagerDownloadRequest new];
     [downloadRequest setBucket:S3BucketNameForProductImage];
     [downloadRequest setKey:filename];
     [downloadRequest setDownloadingFileURL:sourceURL];
     [showroomGroupDownloadRequests addObject:downloadRequest];

    AWSTask *task = [[AWSS3TransferManager defaultS3TransferManager] download:downloadRequest];
    [task continueWithBlock:^id(AWSTask *task) {
    // handle each individual operation
    if (task.error == nil) {

    }
    else if (task.error) {

    }
    // add to the tasks
    [uniqueTasks addObject:task];

    return nil;
}

[[AWSTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(AWSTask *task) {
    if (task.error == nil) {
        // all downloads succeess
    }
    else if (task.error != nil) {
        // failure happen one of download
    }

   return nil;
}];

答案 1 :(得分:0)

某些请求似乎消失的原因是您将AWSS3TransferManagerDownloadRequest定义为属性。 self.downloadRequest1 = nil;在后​​台线程上执行,执行[transferManager download:self.downloadRequest1]时,self.downloadRequest1可能是nil

您应该删除该属性,只需传递AWSS3TransferManagerDownloadRequest的实例作为- downloadFiles:的参数。