How to upload a UIImage to S3 with AWS iOS SDK v2
You can apparently do it with "presigned URLs"
- (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;
}];
}
Documented in the S3 docs for v2 SDK at http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html#use-pre-signed-urls-to-transfer-objects-in-the-background
Its a bit of a mess with nested completion blocks, but the gist is you request a url, then when that returns you start an upload task. This was for a prototype test, not polished code. You should check the status code on the upload instead of just the error.
Even though AWSiOSSDKv2 doesn't support uploading images from memory, you can save it as a file and then upload it.
//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;
}];
It seems that AWSiOSSDKv2 don't have support to upload images from memory at this moment :(
From a Github issue:
The decision to accept only file NSURLs was driven by the following factors:
- Since v1, the pause / resume features require the input to be files. It's not possible to recover NSData and retry the transfer when the app is killed.
- The background transfer on iOS 7 and above only supports files. Currently, we don't support background transfer, but we are planning to support it in the future. We considered accepting an NSData and internally persisting the data to a temporary directory.
- We decided not to include this in 2.0 release because if the NSData is backed by a file, it doubles the disk usage for the data. Also, developers have to deal with disk related errors when using S3TransferManager. Even though we decided not to accept NSData in 2.0 release, we are open for your feedback. If this is a feature you want to see in the future release, please create a new issue with the feature request.
```