2013-10-20 45 views
13

私は現在アマゾンS3に画像をアップロードしているアプリがあります。 NSURLConnectionからNSURLSessionへの切り替えを試みているので、アプリがバックグラウンドにある間にアップロードを続けることができます!私はちょっとした問題にぶつかっているようだ。 NSURLRequestが作成され、NSURLSessionに渡されますが、ファイルを完全にアップロードするNSURLConnectionに同じリクエストを渡すと、amazonは403 - 禁止された応答を返します。ここでNSURLSessionとamazon S3のアップロード

はレスポンスを作成するコードです:

NSString *requestURLString = [NSString stringWithFormat:@"http://%@.%@/%@/%@", BUCKET_NAME, AWS_HOST, DIRECTORY_NAME, filename]; 
NSURL *requestURL = [NSURL URLWithString:requestURLString]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL 
                 cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData 
                timeoutInterval:60.0]; 
// Configure request 
[request setHTTPMethod:@"PUT"]; 
[request setValue:[NSString stringWithFormat:@"%@.%@", BUCKET_NAME, AWS_HOST] forHTTPHeaderField:@"Host"]; 
[request setValue:[self formattedDateString] forHTTPHeaderField:@"Date"]; 
[request setValue:@"public-read" forHTTPHeaderField:@"x-amz-acl"]; 
[request setHTTPBody:imageData]; 

そしてこれは、応答(私はこれがSO答える他から来たと思います)に署名:私はこのラインを使用する場合は、

NSString *contentMd5 = [request valueForHTTPHeaderField:@"Content-MD5"]; 
NSString *contentType = [request valueForHTTPHeaderField:@"Content-Type"]; 
NSString *timestamp = [request valueForHTTPHeaderField:@"Date"]; 

if (nil == contentMd5) contentMd5 = @""; 
if (nil == contentType) contentType = @""; 

NSMutableString *canonicalizedAmzHeaders = [NSMutableString string]; 

NSArray *sortedHeaders = [[[request allHTTPHeaderFields] allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 

for (id key in sortedHeaders) 
{ 
    NSString *keyName = [(NSString *)key lowercaseString]; 
    if ([keyName hasPrefix:@"x-amz-"]){ 
     [canonicalizedAmzHeaders appendFormat:@"%@:%@\n", keyName, [request valueForHTTPHeaderField:(NSString *)key]]; 
    } 
} 

NSString *bucket = @""; 
NSString *path = request.URL.path; 
NSString *query = request.URL.query; 

NSString *host = [request valueForHTTPHeaderField:@"Host"]; 

if (![host isEqualToString:@"s3.amazonaws.com"]) { 
    bucket = [host substringToIndex:[host rangeOfString:@".s3.amazonaws.com"].location]; 
} 

NSString* canonicalizedResource; 

if (nil == path || path.length < 1) { 
    if (nil == bucket || bucket.length < 1) { 
     canonicalizedResource = @"/"; 
    } 
    else { 
     canonicalizedResource = [NSString stringWithFormat:@"/%@/", bucket]; 
    } 
} 
else { 
    canonicalizedResource = [NSString stringWithFormat:@"/%@%@", bucket, path]; 
} 

if (query != nil && [query length] > 0) { 
    canonicalizedResource = [canonicalizedResource stringByAppendingFormat:@"?%@", query]; 
} 

NSString* stringToSign = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n%@%@", [request HTTPMethod], contentMd5, contentType, timestamp, canonicalizedAmzHeaders, canonicalizedResource]; 

NSString *signature = [self signatureForString:stringToSign]; 

[request setValue:[NSString stringWithFormat:@"AWS %@:%@", self.S3AccessKey, signature] forHTTPHeaderField:@"Authorization"]; 

をコードの:

[NSURLConnection connectionWithRequest:request delegate:self]; 

それが動作し、ファイルをアップロードし、私が使用している場合:

NSURLSessionUploadTask *task = [self.session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:filePath]]; 
[task resume]; 

私は禁じられたエラーを受け取ります..!?

誰もがこれを使ってS3にアップロードしようとしましたが、同様の問題が発生しましたか?セッションが一時停止してアップロードを再開する方法と関係があるのだろうか、それともリクエストに面白い何かをしているのだろうか?

可能な解決策の1つは、私が管理している暫定的なサーバーにファイルをアップロードして、それが完了したらS3に転送することです。これは明らかに理想的な解決策ではありません。

ご迷惑をおかけして申し訳ありません。

ありがとうございます!

+0

@ GeogeGreen私はアップロードする必要があります大容量の動画をs3バケツに変換すると、おそらく5GBになるでしょう。NSURLSessionを使ってそれを行うことができます。私が読んだものは、バックグラウンドセッションは長時間実行されません。 –

答えて

2

私はまだNSURLSessionUploadTaskをよく知りませんが、これをどのようにデバッグするかを教えてください。

Charlesのようなツールを使用して、アプリケーションで行われるHTTP(S)要求を確認できます。この問題は、NSURLSessionUploadTaskが設定したヘッダーを無視するか、またはAmazonのS3がファイルのアップロードを想定しているのとは異なるHTTPメソッドを使用している可能性があります。これは、代行受信プロキシを使用して簡単に確認できます。

また、Amazon S3が403のようなエラーを返した場合、実際にはエラーに関する情報を含むXMLドキュメントが返されます。おそらく応答ボディを取得できるNSURLSessionの代理メソッドがありますか?そうでなければチャールズは確かにあなたにもっと洞察力を与えます。

+0

本当に助かりました。私がリクエストに署名した後、Appleは余分なヘッダーフィールドを追加していました! –

+0

@GeorgeGreenさらに詳しい情報を提供できますか?どのようにこれを最終的に克服しましたか? – Stavash

+0

@GeorgeGreen私もとても興味があります。 – Andy

1

私はちょうどその時を過ごして、ついに成功しました。最善の方法は、AWSライブラリを使用して、署名付きヘッダーでリクエストを作成し、リクエストをコピーすることです。 NSURLSessionTaskが別の方法で失敗するため、要求をコピーすることが重要です。以下のコード例では、AFNetworkingとサブクラスAFHTTPSessionManagerを使用しましたが、このコードはNSURLSessionでも機能します。

@implementation MyAFHTTPSessionManager 
    { 

    } 

    static MyAFHTTPSessionManager *sessionManager = nil; 
    + (instancetype)manager { 
     if (!sessionManager) 
      sessionManager = [[MyAFHTTPSessionManager alloc] init]; 
     return sessionManager; 
    } 

    - (id)init { 
     NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration   backgroundSessionConfiguration:toutBackgroundSessionNameAF]; 
     sessionConfiguration.timeoutIntervalForRequest = 30; 
     sessionConfiguration.timeoutIntervalForResource = 300; 
     self = [super initWithSessionConfiguration:sessionConfiguration]; 
     if (self) 
     { 
     } 
     return self; 
    } 

    - (NSURLSessionDataTask *)POSTDataToS3:(NSURL *)fromFile 
           Key:(NSString *)key 
         completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler 
    { 
     S3PutObjectRequest *s3Request = [[S3PutObjectRequest alloc] initWithKey:key inBucket:_s3Bucket]; 
     s3Request.cannedACL = [S3CannedACL publicReadWrite]; 
     s3Request.securityToken = [CTUserDefaults awsS3SessionToken]; 
     [s3Request configureURLRequest]; 
     NSMutableURLRequest *request = [_s3Client signS3Request:s3Request]; 
     // For some reason, the signed S3 request comes back with '(null)' as a host. 
     NSString *urlString = [NSString stringWithFormat:@"%@/%@/%@", _s3Client.endpoint, _s3Bucket, [key stringWithURLEncoding]] ; 
     request.URL = [NSURL URLWithString:urlString]; 
     // Have to create a new request and copy all the headers otherwise the NSURLSessionDataTask will fail (since request get a pointer back to AmazonURLRequest which is a subclass of NSMutableURLRequest) 
     NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]]; 
     [request2 setHTTPMethod:@"PUT"]; 
     [request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]]; 
     NSURLSessionDataTask *task = [self uploadTaskWithRequest:request2 
               fromFile:fromFile 
               progress:nil 
             completionHandler:completionHandler]; 
     return task; 
    } 

    @end  

もう一つの良いリソースは、私はそれがあるZeevのVAX回答に基づいて働かせたリンゴのサンプルコードhereと「シンプルなバックグラウンド転送」

8

を探しています。私は、私が遭遇した問題についていくつかの洞察を提供し、マイナーな改善を提供したいと思います。

通常PutRequestを構築し、インスタンス

S3PutObjectRequest* putRequest = [[S3PutObjectRequest alloc] initWithKey:keyName inBucket:bucketName]; 

putRequest.credentials = credentials; 
putRequest.filename = theFilePath; 

のために今、私たちは私たち

// set the endpoint, so it is not null 
putRequest.endpoint = s3Client.endpoint; 

// if you are using session based authentication, otherwise leave it out 
putRequest.securityToken = messageTokenDTO.securityToken; 

// sign the request (also computes md5 checksums etc.) 
NSMutableURLRequest *request = [s3Client signS3Request:putRequest]; 

今すぐ新しい要求にそのすべてをコピーするためS3Clientは通常ありませんいくつかの作業を行う必要があります。 Amazonは今、私たちはこれがバックグラウンドセッションを作成するコードである実際の転送

NSURLSession* backgroundSession = [self backgroundSession]; 
_uploadTask = [backgroundSession uploadTaskWithRequest:request2 fromFile:[NSURL fileURLWithPath:theFilePath]]; 
[_uploadTask resume]; 

を開始することができます例外

NSMutableURLRequest* request2 = [[NSMutableURLRequest alloc]initWithURL:request.URL]; 
[request2 setHTTPMethod:request.HTTPMethod]; 
[request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]]; 

の原因となる、独自のNSUrlRequestクラスを使用します。

- (NSURLSession *)backgroundSession { 
    static NSURLSession *session = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 

     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.my.unique.id"]; 
     session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 
    }); 

    return session; 
} 

それは、セッション/タスクデリゲートが認証チャレンジを処理する必要があることを理解するまで私はしばらく時間がかかりました(実際にはs3に認証されています)。だからここで

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { 
    NSLog(@"session did receive challenge"); 
    completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); 
} 
+0

ありがとうございます。これは非常にうまく動作します – honcheng

+1

あらかじめ歌った認証を使ってこれをどうやって行いますか?クライアントはaccessKeyと署名のみを持ちますが、これはあなたが鍵と秘密を持っていることを前提としています。 –

+0

私は実際にFederationTokenを使用して以前に一時的な資格情報を生成しています(http://docs.aws.amazon.com/STS/latest/APIReference/API_GetFederationToken.html)。私は事前に署名されたURLを使用したことはありませんが、私がドキュメントを理解する限り、生成されたURLへの単純なURL要求です。 AWS SDKメソッドを使用する必要はありません。AWS統合を一切持たずにNSUrlSessionUploadTaskを作成するだけです。 –

2

を実装すると、タスクを実行するために私のコードです:

AmazonS3Client *s3Client = [[AmazonS3Client alloc] initWithAccessKey:accessKey withSecretKey:secretKey]; 
S3PutObjectRequest *s3PutObjectRequest = [[S3PutObjectRequest alloc] initWithKey:[url lastPathComponent] inBucket:bucket]; 
s3PutObjectRequest.cannedACL = [S3CannedACL publicRead]; 
s3PutObjectRequest.endpoint = s3Client.endpoint; 
s3PutObjectRequest.contentType = fileMIMEType([url absoluteString]); 
[s3PutObjectRequest configureURLRequest]; 

NSMutableURLRequest *request = [s3Client signS3Request:s3PutObjectRequest]; 
NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc]initWithURL:request.URL]; 
[request2 setHTTPMethod:request.HTTPMethod]; 
[request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]]; 

NSURLSessionUploadTask *task = [[self backgroundURLSession] uploadTaskWithRequest:request2 fromFile:url]; 
[task resume]; 

私は、ここに答えが少し古くなっている私のS3の背景には、https://github.com/genadyo/S3Uploader/

+0

リンクのみの回答はお勧めしません。あなたの答えにあなたのソリューションの顕著な側面を含めるか、この答えを削除してコメントを残してください。 – Rob

+0

@Genadyはとにかくインターネット接続が落ちたらアップロードを再開できますか? –

+0

興味深い質問、私はまだそれを試していない。 –

5

をアップロード調達の多くを費やし開きますSwiftと新しいAWS SDKでこの作業をしようとしていました。だからここ(バージョン2.0.7+で利用可能)新しいAWSS3PreSignedURLBuilderを使用することによりスウィフトでそれを行う方法は次のとおりです。背景アップロードするための

class S3BackgroundUpload : NSObject { 

    // Swift doesn't support static properties yet, so have to use structs to achieve the same thing. 
    struct Static { 
     static var session : NSURLSession? 
    } 

    override init() { 
     super.init() 

     // Note: There are probably safer ways to store the AWS credentials. 
     let configPath = NSBundle.mainBundle().pathForResource("appconfig", ofType: "plist") 
     let config = NSDictionary(contentsOfFile: configPath!) 
     let accessKey = config.objectForKey("awsAccessKeyId") as String? 
     let secretKey = config.objectForKey("awsSecretAccessKey") as String? 
     let credentialsProvider = AWSStaticCredentialsProvider .credentialsWithAccessKey(accessKey!, secretKey: secretKey!) 

     // AWSRegionType.USEast1 is the default S3 endpoint (use it if you don't need specific endpoints such as s3-us-west-2.amazonaws.com) 
     let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider) 

     // This is setting the configuration for all AWS services, you can also pass in this configuration to the AWSS3PreSignedURLBuilder directly. 
     AWSServiceManager.defaultServiceManager().setDefaultServiceConfiguration(configuration) 

     if Static.session == nil { 
      let configIdentifier = "com.example.s3-background-upload" 

      var config : NSURLSessionConfiguration 
      if NSURLSessionConfiguration.respondsToSelector("backgroundSessionConfigurationWithIdentifier:") { 
       // iOS8 
       config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(configIdentifier) 
      } else { 
       // iOS7 
       config = NSURLSessionConfiguration.backgroundSessionConfiguration(configIdentifier) 
      } 

      // NSURLSession background sessions *need* to have a delegate. 
      Static.session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil) 
     } 
    } 

    func upload() { 
     let s3path = "/some/path/some_file.jpg" 
     let filePath = "/var/etc/etc/some_file.jpg" 

     // Check if the file actually exists to prevent weird uncaught obj-c exceptions. 
     if NSFileManager.defaultManager().fileExistsAtPath(filePath) == false { 
      NSLog("file does not exist at %@", filePath) 
      return 
     } 

     // NSURLSession needs the filepath in a "file://" NSURL format. 
     let fileUrl = NSURL(string: "file://\(filePath)") 

     let preSignedReq = AWSS3GetPreSignedURLRequest() 
     preSignedReq.bucket = "bucket-name" 
     preSignedReq.key = s3path 
     preSignedReq.HTTPMethod = AWSHTTPMethod.PUT     // required 
     preSignedReq.contentType = "image/jpeg"      // required 
     preSignedReq.expires = NSDate(timeIntervalSinceNow: 60*60) // required 

     // The defaultS3PreSignedURLBuilder uses the global config, as specified in the init method. 
     let urlBuilder = AWSS3PreSignedURLBuilder.defaultS3PreSignedURLBuilder() 

     // The new AWS SDK uses BFTasks to chain requests together: 
     urlBuilder.getPreSignedURL(preSignedReq).continueWithBlock { (task) -> AnyObject! in 

      if task.error != nil { 
       NSLog("getPreSignedURL error: %@", task.error) 
       return nil 
      } 

      var preSignedUrl = task.result as NSURL 
      NSLog("preSignedUrl: %@", preSignedUrl) 

      var request = NSMutableURLRequest(URL: preSignedUrl) 
      request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData 

      // Make sure the content-type and http method are the same as in preSignedReq 
      request.HTTPMethod = "PUT" 
      request.setValue(preSignedReq.contentType, forHTTPHeaderField: "Content-Type") 

      // NSURLSession background session does *not* support completionHandler, so don't set it. 
      let uploadTask = Static.session?.uploadTaskWithRequest(request, fromFile: fileUrl) 

      // Start the upload task: 
      uploadTask?.resume() 

      return nil 
     } 
    } 
} 

extension S3BackgroundUpload : NSURLSessionDelegate { 

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) { 
     NSLog("did receive data: %@", NSString(data: data, encoding: NSUTF8StringEncoding)) 
    } 

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) { 
     NSLog("session did complete") 
     if error != nil { 
      NSLog("error: %@", error!.localizedDescription) 
     } 
     // Finish up your post-upload tasks. 
    } 
} 
+0

V2 apiを使用してS3バケットに動画をアップロードしたい場合、一時停止と再開機能をサポートする必要があります。このコードスニペットのobjcバージョンを使用してアップロードできます –

2

/バックグラウンド構成でNSURLSessionを使用する必要があり、ダウンロード。 AWS SDKを使用して、事前に署名した要求を使用することができます2.0.7以来:

PreSigned URL Builderは、** - SDKは現在、事前に署名 アマゾンシンプルなストレージサービス(S3)URLのサポートが含まれています。これらのURLを使用して、 NSURLSessionクラスを使用してバックグラウンド転送を実行できます。

初期化の背景NSURLSessionとAWSサービス

- (void)initBackgroundURLSessionAndAWS 
{ 
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:AWSS3BackgroundSessionUploadIdentifier]; 
    self.urlSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 
    AWSServiceConfiguration *configuration = [AWSServiceConfiguration configurationWithRegion:DefaultServiceRegionType credentialsProvider:credentialsProvider]; 
    [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; 
    self.awss3 = [[AWSS3 alloc] initWithConfiguration:configuration]; 
} 

- (void)uploadFile 
{ 
    AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new]; 
    getPreSignedURLRequest.bucket = @"your_bucket"; 
    getPreSignedURLRequest.key = @"your_key"; 
    getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT; 
    getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600]; 
    //Important: must set contentType for PUT request 
    getPreSignedURLRequest.contentType = @"your_contentType"; 

    [[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest] continueWithBlock:^id(BFTask *task) { 
     if (task.error) 
     { 
      NSLog(@"Error BFTask: %@", task.error); 
     } 
     else 
     { 
      NSURL *presignedURL = task.result; 
      NSLog(@"upload presignedURL is: \n%@", presignedURL); 

      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:presignedURL]; 
      request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; 
      [request setHTTPMethod:@"PUT"]; 
      [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; 

//   Background NSURLSessions do not support the block interfaces, delegate only. 
      NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:@"file_path"]; 

      [uploadTask resume]; 
     } 
     return nil; 
    }]; 
} 

NSURLSession委任機能アップロードファイル機能を実装します。

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 
{ 
    if (error) 
    { 
     NSLog(@"S3 UploadTask: %@ completed with error: %@", task, [error localizedDescription]); 
    } 
    else 
    { 
//  AWSS3GetPreSignedURLRequest does not contain ACL property, so it has to be set after file was uploaded 
     AWSS3PutObjectAclRequest *aclRequest = [AWSS3PutObjectAclRequest new]; 
     aclRequest.bucket = @"your_bucket"; 
     aclRequest.key = @"yout_key"; 
     aclRequest.ACL = AWSS3ObjectCannedACLPublicRead; 

     [[self.awss3 putObjectAcl:aclRequest] continueWithBlock:^id(BFTask *bftask) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (bftask.error) 
       { 
        NSLog(@"Error putObjectAcl: %@", [bftask.error localizedDescription]); 
       } 
       else 
       { 
        NSLog(@"ACL for an uploaded file was changed successfully!"); 
       } 
      }); 
      return nil; 
     }]; 
    } 
} 
0

最近Amazonが2.2にそこAWS APIを更新しました.4。 このアップデートの専門は、をアップロードしています。をアップロードしているので、NSURLSessionを使ってビデオをアップロードする必要はありません。次のソースブロックを使用してテストすることができます。 AppDelegateの以前のバージョンより30 - 40%高速です。

AWS V2構成アップロードクラスの

AWSStaticCredentialsProvider *staticProvider = [[AWSStaticCredentialsProvider alloc] initWithAccessKey:@"xxxx secretKey:@"xxxx"]; 

AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2                 credentialsProvider:staticProvider]; 

AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration; 

handleEventsForBackgroundURLSession方法で

[AWSS3TransferUtility interceptApplication:application 
     handleEventsForBackgroundURLSession:identifier 
         completionHandler:completionHandler]; 

NSURL *fileURL = // The file to upload. 

AWSS3TransferUtilityUploadExpression *expression = [AWSS3TransferUtilityUploadExpression new]; 
expression.uploadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // Do something e.g. Update a progress bar. 
    }); 
}; 

AWSS3TransferUtilityUploadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtilityUploadTask *task, NSError *error) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // Do something e.g. Alert a user for transfer completion. 
     // On failed uploads, `error` contains the error object. 
    }); 
}; 

AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility]; 
[[transferUtility uploadFile:fileURL 
         bucket:@"YourBucketName" 
         key:@"YourObjectKeyName" 
       contentType:@"text/plain" 
        expression:expression 
      completionHander:completionHandler] continueWithBlock:^id(AWSTask *task) { 
    if (task.error) { 
     NSLog(@"Error: %@", task.error); 
    } 
    if (task.exception) { 
     NSLog(@"Exception: %@", task.exception); 
    } 
    if (task.result) { 
     AWSS3TransferUtilityUploadTask *uploadTask = task.result; 
     // Do something with uploadTask. 
    } 

    return nil; 
}]; 

より参照のためのm個のdidFinishLaunchingWithOptions方法 //〜GM〜セットアップcognito:https://aws.amazon.com/blogs/mobile/amazon-s3-transfer-utility-for-ios/

関連する問題