简体   繁体   English

从Amazon S3 Bucket iOS下载多个项目

[英]Download Multiple Items from Amazon S3 Bucket iOS

I've recently implemented the new AWS 2.0 iOS SDK in my application (yay, cocoapods!), and using the sample code from Amazon managed to properly configure access and downloads. 我最近在我的应用程序中实现了新的AWS 2.0 iOS SDK(yay,cocoapods!),并使用Amazon管理的示例代码来正确配置访问和下载。 I can successfully download a single item without issue, but I need to be able to download multiple files dynamically generated based on the current tableview. 我可以毫无问题地成功下载单个项目,但我需要能够下载基于当前tableview动态生成的多个文件。 There doesn't appear to be a way to set up a batch download, so I'm simply trying to loop through an array of objects and trigger a download with each one. 似乎没有办法设置批量下载,所以我只是尝试遍历一个对象数组并触发每个对象的下载。 It works, but if the list includes more than a few items, it starts randomly misfiring. 它可以工作,但如果列表包含多个项目,它会随机开始失火。 For example, if my dynamically created list has 14 items in it, 12 will be downloaded, and the other 2 aren't even attempted. 例如,如果我的动态创建列表中有14个项目,则将下载12个项目,而其他2个项目甚至都未尝试。 The request just vanishes. 请求消失了。 In my testing, I added a sleep(1) timer, and then all 14 are triggered and downloaded, so I'm guessing that I'm overwhelming the download requests and they are getting dropped unless I slow it down. 在我的测试中,我添加了一个sleep(1)计时器,然后全部14个被触发并下载,所以我猜测我压倒了下载请求并且它们会被丢弃,除非我放慢速度。 Slowing it down is not ideal... perhaps there is another way? 减慢它并不理想...也许还有另一种方式? Here is the code: 这是代码:

 - (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];

 }

That launches the downloadFiles method: 那将启动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;
}];        
 }

There has got to be a way to download a dynamic list of files from an Amazon S3 bucket, right? 必须有一种从Amazon S3存储桶下载动态文件列表的方法,对吧? Maybe there is a transfer manager that allows an array of files instead of doing them individually? 也许有一个传输管理器允许一组文件而不是单独执行它们?

Any and all help is appreciated. 任何和所有的帮助表示赞赏。 Zack 扎克

Sounds like request timeout interval setting issue. 听起来像请求超时间隔设置问题。

First, when you configure AWSServiceConfiguration *configuration = ... try to configure the timeoutIntervalForRequest property. 首先,当您配置AWSServiceConfiguration *configuration = ...尝试配置timeoutIntervalForRequest属性。 Also, maxRetryCount as well. 另外,还有maxRetryCount maxRetryCount will attempt to download if failure for downloading each operation. 如果下载每个操作失败, maxRetryCount将尝试下载。

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

Second, for the multiple items downloading try to collect each AWSTask into one array and get the result at the end of group operation. 其次,对于多个项目下载尝试将每个AWSTask收集到一个数组中并在组操作结束时获得结果。 ex) EX)

// 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;
}];

The reason some requests seem to vanish is that you define AWSS3TransferManagerDownloadRequest as a property. 一些请求似乎消失的原因是您将AWSS3TransferManagerDownloadRequest定义为属性。 self.downloadRequest1 = nil; is executed on the background thread, and it is possible that when [transferManager download:self.downloadRequest1] is executed, self.downloadRequest1 is nil . 在后台线程上执行,并且当执行[transferManager download:self.downloadRequest1]self.downloadRequest1nil

You should remove the property and simply pass an instance of AWSS3TransferManagerDownloadRequest as an argument for - downloadFiles: . 你应该删除该属性,只需传递一个AWSS3TransferManagerDownloadRequest实例作为参数- downloadFiles: .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM