ios - Amazon AWSS3TransferManager 在 ios 中无法上传多部分数据

标签 ios objective-c amazon-web-services awss3transfermanager

我正在尝试将 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];

关于ios - Amazon AWSS3TransferManager 在 ios 中无法上传多部分数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43612490/

相关文章:

objective-c - 使用代理时,NSURLConnection 会泄漏 https URL

ios - 无法从 LinkedIn API 获取完整的个人资料详细信息

javascript - 通过 javascript 和凭证提供商进行身份验证的 AWS API 网关

ios - 从 TimerCallback 实例调用时,调用 Dropbox API Client.Files.DownloadAsync 不会返回元数据

ios - 从另一个 ViewController 访问数组并对其进行排序

ios - 以编程方式编辑通讯簿的名字和姓氏

amazon-web-services - AWS Glue 作业 - 将 CSV 转换为 Parquet

ios - 在 iOS 中同时使用两个音频单元进行 I/O 是否安全?

objective-c - KVO 和更改 UI 值更改

mongodb - AWS Lambda 和 MongoDB