2017-04-25 103 views
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