Jak przesłać UIImage do S3 z AWS iOS SDK v2

Strona README w Github ( https://github.com/aws/aws-sdk-ios-v2 ) ma już przykład przesłania obrazu, z adresu URL ścieżki pliku:

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

Ale co jeśli mam tylko UIImage w pamięci (bez ścieżki do pliku)? Czy można wgrać UIImage (lub jest to NSData) do S3 używając SDK?

Czy byłoby łatwiej ręcznie używać HTTP API (używając czegoś w rodzaju AFNetworking)?

Author: Syed Ali Salman, 2014-08-18

6 answers

Nawet jeśli AWSiOSSDKv2 nie obsługuje przesyłania obrazów z pamięci, możesz zapisać je jako plik, a następnie przesłać.

//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;
}];
 19
Author: Rick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-24 08:16:25

Wygląda na to, że AWSiOSSDKv2 nie ma w tej chwili wsparcia dla wgrywania obrazków z pamięci : (

From a Github issue :

Decyzja o przyjęciu tylko Pliku Nsurl była podyktowana następującymi czynniki:

  1. od wersji v1 funkcje pauzy / wznowienia wymagają, aby dane wejściowe były pliki. Nie jest możliwe odzyskanie NSData i ponowna próba transferu, gdy aplikacja nie działa.
  2. transfer w tle tylko na iOS 7 i nowszych obsługuje pliki. Obecnie nie obsługujemy transferu w tle, ale planujemy go wspierać w przyszłości. Rozważaliśmy przyjęcie NSData i wewnętrznie utrzymywanie danych w katalogu tymczasowym.
  3. zdecydowaliśmy się nie włączać tego w wydaniu 2.0, ponieważ jeśli nsdata jest wspierany przez plik, podwaja zużycie dysku dla danych. Również, programiści mają do czynienia z błędami związanymi z dyskami podczas korzystania S3TransferManager. Mimo, że zdecydowaliśmy się nie akceptować NSData w 2.0 uwolnij, my jesteśmy otwarci na Wasze opinie. Jeśli jest to funkcja, którą chcesz aby zobaczyć w przyszłym wydaniu, utwórz nowy numer z żądanie funkcji.

```

 11
Author: tothemario,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-18 22:39:03

Możesz najwyraźniej zrobić to za pomocą "presigned 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;

  }];
}

Udokumentowane w S3 docs for V2 SDK w http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html#use-pre-signed-urls-to-transfer-objects-in-the-background

To trochę bałagan z zagnieżdżonymi blokami końcowymi, ale gist polega na tym, że żądasz adresu url, a gdy to powróci, rozpoczynasz zadanie przesyłania. To był test prototypu, a nie dopracowany kod. Należy sprawdzić kod statusu na upload zamiast tylko błędu.

 2
Author: Brian Broom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-28 19:08:29

To jest zaktualizowana odpowiedź, więc ludzie nie muszą sami (tak jak ja): d

Importuj odpowiednie pliki (Pobierz tutaj)

#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;
}

Użyłem przycisku, aby wiedzieć, kiedy użytkownik chce przesłać plik

- (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;
                                        }];
}

Helpfull links:

AWS Documentation

YouTube Video

Mam nadzieję, że to komuś pomoże!
 2
Author: Lazar Kukolj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-10 06:32:20

Cześć możesz piaskować obraz bez zapisywania obrazu w folderze tymczasowym w iPhonie Amazon iOS v2 daje taką opcję.

W tym kodzie logFile.body jest to NSData.

Ten kod ci pomoże, przyjacielu.
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");
  }
}
 0
Author: Oleg Gordiichuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-22 11:02:07

W bieżącej wersji SDK możesz użyć AWSS3TransferUtility, a następnie zrobi wszystko za Ciebie.

func uploadData() {

   let data: Data = Data() // Data to be uploaded

   let expression = AWSS3TransferUtilityUploadExpression()
      expression.progressBlock = {(task, progress) in
         DispatchQueue.main.async(execute: {
           // Do something e.g. Update a progress bar.
        })
   }

   var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
   completionHandler = { (task, error) -> Void in
      DispatchQueue.main.async(execute: {
         // Do something e.g. Alert a user for transfer completion.
         // On failed uploads, `error` contains the error object.
      })
   }

   let transferUtility = AWSS3TransferUtility.default()

   transferUtility.uploadData(data,
        bucket: "YourBucket",
        key: "YourFileName",
        contentType: "text/plain",
        expression: expression,
        completionHandler: completionHandler).continueWith {
           (task) -> AnyObject! in
               if let error = task.error {
                  print("Error: \(error.localizedDescription)")
               }

               if let _ = task.result {
                  // Do something with uploadTask.
               }
               return nil;
       }
}
 0
Author: Alper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-04 09:46:15