Amazon AWSS3TransferManager 在 ios 中上传分段数据失败
Amazon AWSS3TransferManager fails in ios to upload multipart data
我正在尝试将 NSData 对象(可以是图像或视频)上传到 Amazon S3。
文件大小小于 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,所以我需要让这段代码以某种方式工作。
感谢任何帮助。
对于遇到同样问题的人,我终于找到了问题所在:
我使用了 OwnAWSCredentialsProvider,作为 AWSCredentialsProvider 的包装器。
此处,凭据的 getter 始终返回 nil(不确定为什么它适用于小文件)。
相反,我现在使用由 AWS SDK 提供的 AWSBasicSessionCredentialsProvider,一切正常。
AWSBasicSessionCredentialsProvider *credentialsProvider = [[AWSBasicSessionCredentialsProvider alloc] initWithAccessKey:accessKeyId secretKey:secretAccessKey sessionToken:sessionToken];
我正在尝试将 NSData 对象(可以是图像或视频)上传到 Amazon S3。
文件大小小于 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,所以我需要让这段代码以某种方式工作。
感谢任何帮助。
对于遇到同样问题的人,我终于找到了问题所在:
我使用了 OwnAWSCredentialsProvider,作为 AWSCredentialsProvider 的包装器。
此处,凭据的 getter 始终返回 nil(不确定为什么它适用于小文件)。
相反,我现在使用由 AWS SDK 提供的 AWSBasicSessionCredentialsProvider,一切正常。
AWSBasicSessionCredentialsProvider *credentialsProvider = [[AWSBasicSessionCredentialsProvider alloc] initWithAccessKey:accessKeyId secretKey:secretAccessKey sessionToken:sessionToken];