0

我想上传一个NSData对象(可以是图像或视频)到亚马逊S3。亚马逊AWSS3TransferManager失败在ios上传多部分数据

当文件大小低于5Mb时,一切正常。当它更大时,AWS SDK切换到分段上传,然后失败:

匿名用户无法启动分段上传。请认证。

我正在使用当前可用的最新AWSS3 SDK版本(2.5.5)。

- (void) uploadDataToAWS: (NSData *) mediaData 
      contentType: (NSString *) contentType 
        bucket: (NSString *) bucket 
        region: (NSString *) region 
       objectKey: (NSString *) objectKey 
      accessKeyId: (NSString *) accessKeyId 
     secretAccessKey: (NSString *) secretAccessKey 
      sessionToken: (NSString *) sessionToken 
     progressHandler: (void (^) (int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend)) progressHandler 
    withCompletionHandler: (void (^) (BOOL success)) completionHandler { 

    OwnAWSCredentialsProvider *credentialsProvider = [OwnAWSCredentialsProvider credentialsWithAccessKey:accessKeyId secretKey:secretAccessKey sessionKey:sessionToken]; 
    AWSServiceConfiguration *awsServiceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 
                        credentialsProvider:credentialsProvider]; 
    [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = awsServiceConfiguration; 

    //Since S3 does not support objects uploads (only files), will write first locally: 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.forUpload", [self randomStringWithLength:10]]]; 
    [mediaData writeToFile:filePath atomically:YES]; 

    //Configure upload request 
    AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new]; 
    uploadRequest.bucket = bucket; 
    uploadRequest.key = objectKey; 
    uploadRequest.body = [NSURL fileURLWithPath:filePath]; 
    uploadRequest.contentType = contentType; 

    uploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend){ 
     progressHandler (bytesSent, totalBytesSent, totalBytesExpectedToSend); 
    }; 

    AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager]; 

    [[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor] withBlock:^id(AWSTask *task) { 
     //Remove the generated file 
     [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; 

     if (task.error != nil) { 
      if(task.error.code != AWSS3TransferManagerErrorCancelled 
       && task.error.code != AWSS3TransferManagerErrorPaused) { 
       NSLog(@"(%i) %@", (int)task.error.code, [task.error localizedDescription]); 
       NSLog(@"Message: %@", task.error.userInfo[@"Message"]); 
      } 
      completionHandler (NO); 
     } else { 
      completionHandler(YES); 
     } 
     return task; 
    }]; 
} 

OwnAWSCredentialsProvider.m:

#import "OwnAWSCredentialsProvider.h" 

@implementation OwnAWSCredentialsProvider 

+ (instancetype)credentialsWithAccessKey:(NSString *)accessKey 
           secretKey:(NSString *)secretKey 
           sessionKey:(NSString*)sessionKey 
{ 
    OwnAWSCredentialsProvider *credentials = [[OwnAWSCredentialsProvider alloc] initWithAccessKey:accessKey secretKey:secretKey sessionKey:sessionKey]; 
    return credentials; 
} 

- (instancetype)initWithAccessKey:(NSString *)accessKey 
         secretKey:(NSString *)secretKey 
         sessionKey:(NSString*)sessionKey 
{ 
    if (self = [super init]) { 
     _accessKey = accessKey; 
     _secretKey = secretKey; 
     _sessionKey = sessionKey; 
    } 
    return self; 
} 

- (AWSTask<AWSCredentials *> *)credentials { 
    return [[AWSTask taskWithResult:nil] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) { 
     return task; 
    }]; 
} 

- (void)invalidateCachedTemporaryCredentials { 
} 

@end 

凭据在每个上传生成,它们是有效的,对超过5MB小文件伟大的工作。

我不使用预先签名的URL,所以我需要让这段代码以某种方式工作。

任何帮助表示赞赏。

回答

1

对于具有相同问题的人,我终于找到了在那里有问题:

我用OwnAWSCredentialsProvider,作为AWSCredentialsProvider的包装。

在这里,凭证的getter总是返回零(不知道为什么它适用于小文件)。

相反,我现在正在使用由AWS SDK提供的AWSBasicSessionCredentialsProvider,并且一切正常。

AWSBasicSessionCredentialsProvider *credentialsProvider = [[AWSBasicSessionCredentialsProvider alloc] initWithAccessKey:accessKeyId secretKey:secretAccessKey sessionToken:sessionToken]; 
+0

这个方法中的“sessionToken”是什么? –

+0

我从我的服务器获取accessKeyId,secretAccessKey和sessionToken,这是从AWS请求的。然后我在我的上传方法中使用它们。 – CristiC