4

NSURLSessionUploadTask を使用してバックグラウンド セッションで実行できる PUT 経由でコンテンツを AWS S3 にアップロードする必要があります。

これまでのところ、うまく機能しています。ただし、S3 へのアップロードが完了したら、状態を完了に変更するために API を呼び出す必要があります。

AWSS3 で S3 リクエストを作成し、この SO answerに従って NSURLSessionUploadTask にコピーします。これはフォアグラウンドとバックグラウンドの両方で実行され、ファイルが S3 に正常にアップロードされます。

今、これは私が助けを必要としている部分です。URLSession:task:didCompleteWithError と URLSessionDidFinishEventsForBackgroundURLSession の両方のデリゲート メソッドを使用して追加の API リクエストを呼び出そうとしました。もう一度アプリを開きます。理想的には、すぐに発砲してもらいたいです。アップロードの発砲はフォアグラウンドにあります。バックグラウンドで私がやろうとしているのとまったく同じことを Wunderlist が行っているのを見たことがあります。

これが私がこれまでに持っているものです...どんな助け/提案も素晴らしいでしょう、これは私を夢中にさせています! :)

- (IBAction)upload:(id)sender {
  AmazonS3Client *s3Client = [[AmazonS3Client alloc] initWithAccessKey:@"ABC" withSecretKey:@"123"];

  NSString *identifier = [NSString stringWithFormat:@"com.journeyhq.backgroundSession.%@-%@", @"S3", @"ATTACHMENT_REMOTE_ID"];
  NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
  NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];

  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *documentsDirectory = [paths objectAtIndex:0];
  NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"img.jpg"];
  NSURL *fromFile = [NSURL fileURLWithPath:filePath isDirectory:NO];

  S3PutObjectRequest *s3Request = [[S3PutObjectRequest alloc] initWithKey:[[NSString stringWithFormat:@"%@__%@__%@", @"ATTACHMENT_ID", @"ATTACHMENT_UUID", @"img.jpg"] lowercaseString] inBucket:@"BUCKET_NAME"];
  s3Request.cannedACL = [S3CannedACL publicReadWrite];

  NSMutableURLRequest *request = [s3Client signS3Request:s3Request];

  NSString *urlString = [NSString stringWithFormat:@"https://%@.%@/%@", @"BUCKET_NAME", @"s3-eu-west-1.amazonaws.com", [[NSString stringWithFormat:@"%@__%@__%@", @"ATTACHMENT_ID", @"ATTACHMENT_UUID", @"img.jpg"] lowercaseString]];
  request.URL = [NSURL URLWithString:urlString];

  NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  [request2 setHTTPMethod:@"PUT"];
  [request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]];
  [request2 setValue:@"BUCKET_NAME.s3-eu-west-1.amazonaws.com" forHTTPHeaderField:@"Host"];

  NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request2 fromFile:fromFile];
  [uploadTask resume];
}

#pragma - NSURLSessionTaskDelegate

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
    dispatch_async(dispatch_get_main_queue(), ^{
      self.progressView.progress = (float)totalBytesSent / (float) totalBytesExpectedToSend;
    });
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
  NSURLSessionConfiguration *sessionConfig = [session configuration];
  NSString *identifier = [sessionConfig identifier];

  NSLog(@"**identifier**: %@", identifier);

  NSArray *identifierComponents = [identifier componentsSeparatedByString:@"."];
  NSString *lastComponent = [identifierComponents lastObject];
  NSArray *components = [lastComponent componentsSeparatedByString:@"-"];
  NSString *sessionType = [components firstObject];
  NSString *attachmentID = [components lastObject];

  NSLog(@"sessionType: %@", sessionType);
  NSLog(@"attachmentID: %@", attachmentID);

  if (error == nil)
  {
    NSLog(@"Task %@ completed successfully", task);
    if ([sessionType isEqualToString:@"S3"]) {
        NSString *downloadIdentifier = [NSString stringWithFormat:@"com.journeyhq.backgroundSession.%@-%@", @"s3Completion", attachmentID];
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:downloadIdentifier];
        NSURLSession *downloadSession = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];

        NSString *urlString = @"API_COMPLETION_URL";
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];

        NSURLSessionDownloadTask *downloadTask = [downloadSession downloadTaskWithRequest:request];
        [downloadTask resume];
    }
  }
  else
  {
    NSLog(@"Task %@ completed with error: %@", task,
          [error localizedDescription]);
  }
  task = nil;

}

AppDelegate.h

- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler {
}

編集次のことも試しました。タスクは以前と同じように作成されますが、タスクを再開しても起動しません。

- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler {

    NSDictionary *userInfo = @{
        @"completionHandler" : completionHandler,
        @"sessionIdentifier" : identifier
    };

    [[NSNotificationCenter defaultCenter]
        postNotificationName:@"BackgroundTransferNotification"
        object:nil
        userInfo:userInfo];
}

次に、ビューコントローラーで

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(handleBackgroundTransfer:)
     name:@"BackgroundTransferNotification"
     object:nil];
}

- (void)handleBackgroundTransfer:(NSNotification *)notification {
    // handle the API call as shown in original example
    ...
}
4

2 に答える 2