Подтвердить что ты не робот

Как загрузить UIImage на S3 с помощью AWS iOS SDK v2

На странице README в Github (https://github.com/aws/aws-sdk-ios-v2) уже есть пример загрузки изображения с URL-адреса пути к файлу:

AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.bucket = yourBucket;
uploadRequest.key = yourKey;
uploadRequest.body = yourDataURL; // <<<< this is a NSURL
uploadRequest.contentLength = [NSNumber numberWithUnsignedLongLong:fileSize];

Но что, если у меня есть только UIImage в памяти (без пути к файлу)? Можно ли загрузить UIImage (или it NSData) на S3 с помощью SDK?

Было бы проще вручную использовать HTTP API (используя что-то вроде AFNetworking)?

4b9b3361

Ответ 1

Кажется, что AWSiOSSDKv2 не поддерживает загрузку изображений из памяти в данный момент: (

Из проблемы Github:

Решение о принятии только файлов NSURL было вызвано следующим факторы:

  • Поскольку v1, функции паузы/возобновления требуют ввода файлы. Невозможно восстановить NSData и повторить передачу, если приложение убито.
  • Фоновая передача только на iOS 7 и выше поддерживает файлы. В настоящее время мы не поддерживаем передачу фона, но мы планируем поддержать его в будущем. Мы решили принять NSData и внутренне сохраняя данные во временном каталоге.
  • Мы решили не включать это в выпуск 2.0, потому что если NSData поддерживаемый файлом, он удваивает использование диска для данных. Также, разработчикам приходится иметь дело с дисковыми ошибками при использовании S3TransferManager. Хотя мы решили не принимать NSData в 2.0 релиз, мы открыты для ваших отзывов. Если это функция, которую вы хотите чтобы увидеть в будущем выпуске, пожалуйста, создайте новую проблему с помощью запрос функции.

`` `

Ответ 2

Несмотря на то, что AWSiOSSDKv2 не поддерживает загрузку изображений из памяти, вы можете сохранить его как файл и загрузить его.

//image you want to upload
UIImage* imageToUpload = [UIImage imageNamed:@"imagetoupload"]; 

//convert uiimage to 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", dateKey]];
[UIImagePNGRepresentation(imageToUpload) writeToFile:filePath atomically:YES];

NSURL* fileUrl = [NSURL fileURLWithPath:filePath];

//upload the image
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.body = fileUrl;
uploadRequest.bucket = AWS_BUCKET_NAME;
uploadRequest.key = @"yourkey";
uploadRequest.contentType = @"image/png";
[[transferManager upload:thumbNailUploadRequest] continueWithExecutor:[BFExecutor mainThreadExecutor] withBlock:^id(BFTask *task) {
    if(task.error == nil) {
        NSLog(@"woot");
    }
    return nil;
}];

Ответ 3

Вы можете сделать это с помощью "назначенных URL-адресов"

- (void)uploadImageToS3: (UIImage *)image {
  NSData *imageData = UIImageJPEGRepresentation(image, 0.7);

  AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
  getPreSignedURLRequest.bucket = @"bucket-name";
  getPreSignedURLRequest.key = @"image-name.jpg";
  getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT;
  getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];

  NSString *fileContentTypeString = @"text/plain";
  getPreSignedURLRequest.contentType = fileContentTypeString;

  [[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest] continueWithBlock:^id(AWSTask *task) {

    if (task.error) {
      NSLog(@"Error: %@", 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:fileContentTypeString forHTTPHeaderField:@"Content-Type"];

      NSURLSessionUploadTask *uploadTask = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        if (error) {
          NSLog(@"Upload errer: %@", error);
        }
        NSLog(@"Done");
      }];

      [uploadTask resume];
    }

    return nil;

  }];
}

Документировано в документах S3 для v2 SDK на http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html#use-pre-signed-urls-to-transfer-objects-in-the-background

Немного беспорядок с вложенными блоками завершения, но суть в том, что вы запрашиваете URL-адрес, а затем, когда он возвращается, вы запускаете задачу загрузки. Это было для прототипа теста, а не для полированного кода. Вы должны проверить код состояния при загрузке, а не только на ошибку.

Ответ 4

Это обновленный ответ, поэтому люди не должны сами это понимать (например, я): D

Импортируйте нужные файлы (скачайте здесь)

#import <AWSCore/AWSCore.h>
#import <AWSS3TransferManager.h>

.m

- (void)viewDidLoad {
    [super viewDidLoad];

    AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
       identityPoolId:@"us-east-1:*******-******-*****-*****-*****"];

    AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1
                                                                     credentialsProvider:credentialsProvider];

    AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
}

Я использовал кнопку, чтобы узнать, когда пользователь хочет загрузить файл

- (void)upload{

    //convert uiimage to
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@".png"]];
    [UIImagePNGRepresentation(YOUR_UIIMAGE) writeToFile:filePath atomically:YES];

    NSURL* fileUrl = [NSURL fileURLWithPath:filePath];

    //upload the image
    AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
    uploadRequest.body = fileUrl;
    uploadRequest.bucket = @"YOUR_BUCKET_NAME";
    uploadRequest.key = @"YOUR_FOLDER_NAME (if you have one)/NEW_IMAGE_NAME.png";
    uploadRequest.contentType = @"image/png";
    uploadRequest.ACL = AWSS3BucketCannedACLPublicRead;

    AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];

    [[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor]
                                                       withBlock:^id(AWSTask *task) {
                                        if (task.error != nil) {
                                            NSLog(@"%s %@","Error uploading :", uploadRequest.key);
                                        }else { NSLog(@"Upload completed"); }
                                            return nil;
                                        }];
}

Полезные ссылки:

AWS Documnetion

Видео YouTube

Надеюсь, это поможет кому-то!

Ответ 5

Привет, вы можете сфотографировать изображение без сохранения изображения во временную папку на iPhone. Amazon iOS v2 также предоставляет такую ​​возможность.

В этом коде logFile.body это NSData.

Этот код поможет вам, мой друг.

AWSS3PutObjectRequest *logFile = [AWSS3PutObjectRequest new];
  logFile.bucket = uploadTokenData_.bucket;
  logFile.key = key;
  logFile.contentType = contentType;
  logFile.body = data_;
  logFile.contentLength = [NSNumber numberWithInteger:[data_ length]];

AWSS3 *S3 = [[AWSS3 alloc] initWithConfiguration:[AWSCredentialsProvider runServiceWithStsCredential]];

AWSS3TransferManager *transferManager = [[AWSS3TransferManager alloc] initWithS3:S3];

[[transferManager.s3 putObject:logFile] continueWithBlock:^id(BFTask *task)
{

  NSLog(@"Error : %@", task.error);
  if (task.error == nil)
  {
    NSLog(@"Uploadet");
  }
}