How to upload Image AWSS3 TransferManager upload Request objective c? - ios

I am working on an app in which I need to upload image using AWSS3. Below is my code. However I am getting error something about pool id not found. I am not sure whats going, Do I need to add anything more.
This is the error getting
Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={__type=ResourceNotFoundException, message=IdentityPool 'ap-northeast-1:xxxxxxx' not found
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#""];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
// get the image from a UIImageView that is displaying the selected Image
// create a local image that we can use to upload to s3
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:#"image.png"];
NSData *imageData = UIImagePNGRepresentation(selectedImage);
[imageData writeToFile:path atomically:YES];
// once the image is saved we can use the path to create a local fileurl
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
// next we set up the S3 upload request manager
AWSS3TransferManagerUploadRequest *_uploadRequest = [AWSS3TransferManagerUploadRequest new];
// set the bucket
_uploadRequest.bucket = #"chatify";
// I want this image to be public to anyone to view it so I'm setting it to Public Read
_uploadRequest.ACL = AWSS3ObjectCannedACLPublicRead;
// set the image's name that will be used on the s3 server. I am also creating a folder to place the image in
_uploadRequest.key = #"ios/image.png";
// set the content type
_uploadRequest.contentType = #"image/png";
// we will track progress through an AWSNetworkingUploadProgressBlock
_uploadRequest.body = url;
__weak ClaimViewController *weakSelf = self;
_uploadRequest.uploadProgress =^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend){
dispatch_sync(dispatch_get_main_queue(), ^{
weakSelf.amountUploaded = totalBytesSent;
weakSelf.filesize = totalBytesExpectedToSend;
[weakSelf update];
});
};
// now the upload request is set up we can creat the transfermanger, the credentials are already set up in the app delegate
AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];
// start the upload
[[transferManager upload:_uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor] withBlock:^id(AWSTask *task) {
// once the uploadmanager finishes check if there were any errors
if (task.error) {
NSLog(#"%#", task.error);
}else{// if there aren't any then the image is uploaded!
// this is the url of the image we just uploaded
NSLog(#"https://s3.amazonaws.com/s3-demo-objectivec/foldername/image.png");
}
return nil;
}];

hi #kashif the error clear says that you need to add the pool id
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#""];
but in the Above code you just pass the Black in identityPoolId
Here's also another method to which provide Credential
AWSStaticCredentialsProvider *credentialsProvider = [AWSStaticCredentialsProvider credentialsWithAccessKey:#"AccessKey" secretKey :#"secretKey"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSWest2
credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;

This error is because of your Cognito Identity Pool being deleted from your account or you setting the region incorrectly. Your region should be set to
AWSRegionAPNorthEast1 based on what I see in the posted code.
Thanks,
Rohan

Related

Amazon s3 transfer utility not working in background

i have to upload a large file like more then 4gb onto amazon s3. amazon sdk giving two options for uploading and downloading from s3. one is awss3transfermanager and other is awss3transferutility. i actually want to use awss3transferutility because i want the app to continue uploading in background. awss3transferutility has two functions uploadFile and other uploadFileUsingMultiPart . uploadFile function actually works in background but uploading starts from 0 on network changes or drop. For that reason i am curretly using uploadFileUsingMultiPart function so the uploading won't get restart from 0 on networks fail. but this uploadFileUsingMultiPart function won't continue uploading in background. In their latest release they introduce this uploadFileUsingMultiPart function inside awstransferutility. so i was expecting that uploading will continue in background with network fail but it won't continue in background. i just wanted to ask is it sdk related bug or i am doing something wrong
this is the code i am curretly
//in app delegate
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler {
[AWSS3TransferUtility interceptApplication:application
handleEventsForBackgroundURLSession:identifier
completionHandler:completionHandler];
}
// in ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
__weak typeof(self) weakSelf = self;
expression = [AWSS3TransferUtilityMultiPartUploadExpression new];
expression.progressBlock = ^(AWSS3TransferUtilityMultiPartUploadTask * task, NSProgress * progress) {
typeof(self) newWeakSelf = weakSelf;
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Alert a user for transfer completion.
NSLog(#"progress value %f",progress.fractionCompleted);
// On failed uploads, `error` contains the error object.
newWeakSelf->progressView.progress = progress.fractionCompleted;
});
};
completionHandler = ^(AWSS3TransferUtilityMultiPartUploadTask *task, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"uploading completed ");
});
};
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#"us-west-1:7a24b199-e4b2-4657-9627-sdfs4ssdff"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
// AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
AWSS3TransferUtilityConfiguration *tfConfig = [AWSS3TransferUtilityConfiguration new];
tfConfig.retryLimit = 5;
tfConfig.multiPartConcurrencyLimit = [NSNumber numberWithInteger:3];
[AWSS3TransferUtility registerS3TransferUtilityWithConfiguration:configuration transferUtilityConfiguration:tfConfig forKey:#"transfer-utility-with-advanced-options"];
transferUtility = [AWSS3TransferUtility S3TransferUtilityForKey:#"transfer-utility-with-advanced-options"];
}
-(void)startUploading {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"mp4"];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSString *fileContentTypeStr = #"video/mp4";
// NSData *data = [NSData dataWithContentsOfURL:fileURL];
// AWSTask *task = [transferUtility uploadDataUsingMultiPart:data bucket:#"sibme-development" key:#"temp/testfilenew/testfile1.mp4" contentType:fileContentTypeStr expression:expression completionHandler:completionHandler ];
AWSTask *task = [transferUtility uploadFileUsingMultiPart:fileURL bucket:#"development" key:#"temp/testfilenew/testfile.mp4" contentType:fileContentTypeStr expression:expression completionHandler:completionHandler];
[task continueWithBlock:^id _Nullable(AWSTask * _Nonnull t) {
if (t.result) {
self->uplaodTask = t.result;
}
return nil;
}];
}
I am not expert on this, but I noticed something in your code - Bucket region:
initWithRegionType:AWSRegionUSEast1
identityPoolId:#"us-west-1:...
Once I had similar mismatch in my code, the bucket region and the Cognito identity pool region did not match, and that was causing problems. This may or may not be the case in your code, but just adding some info based on my experience.
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#"us-west-1:7a24b199-e4b2-4657-9627-sdfs4ssdff"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
If you think there is a bug with the SDK, you can try with the latest version of the SDK and if you are still seeing issues, open an Issue over in https://github.com/aws-amplify/aws-sdk-ios with some repro steps.

Checking Amazon Cognito Roles (Auth vs Unauth)

I am new to using AWS as a backend for my iOS mobile app. I have set up all the roles and identiy pool needed. I have added the following code to my AppDelegate.m file:
// Starting AWS
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#"IdentityPool"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
What is the next step to see if I am authenticated or not? Trying to figue out iOS code to see what role I am in.
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Import service headers where you want to use AWS and then just try to make a call to AWS services.
AWSS3Transfermanager *transferManager = [AWSS3Transfermanager defaultS3TransferManager];
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.bucket = yourBucket;
uploadRequest.key = yourKey;
uploadRequest.body = yourDataURL;
uploadRequest.contentLength = [NSNumber numberWithUnsignedLongLong:fileSize];
[[transferManager upload:uploadRequest] continueWithBlock:^id(AWSTask *task) {
// Do something with the response
return nil;
}];

Upload files to s3 AWSCognitoCredentialsProvider ios

I try to upload file to s3 and I always got next error message
2015-08-05 14:35:53.931 BellyBuds[47981:2189296] Upload failed: [Error
Domain=com.amazonaws.AWSS3ErrorDomain Code=0 "The operation couldn’t
be completed. (com.amazonaws.AWSS3ErrorDomain error 0.)"
UserInfo=0x7fd40a40d8f0
{HostId=wo/bHFvnQjGuiLic3IhL+jicVfeIcuR6M4HXz/nB9WRt/T09h16bbR77nkqKngzj,
Bucket=bbbname, Endpoint=bbstagemusic.s3.amazonaws.com,
Message=The bucket you are attempting to access must be addressed
using the specified endpoint. Please send all future requests to this
endpoint., Code=PermanentRedirect, RequestId=6D250A718C640210}]
AWSCognitoCredentialsProvider *credProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
identityId:[params valueForKey:#"IdentityId"]
identityPoolId:[params valueForKey:#"IdentityPoolId"]
logins:#{#"cognito-identity.amazonaws.com": params[#"Token"]}];
//credProvider.logins = #{ #(AWSCognitoLoginProviderKeyLoginWithAmazon): params[#"Token"] };
AWSServiceConfiguration *serviceConfiguration = [[AWSServiceConfiguration alloc]initWithRegion:AWSRegionUSEast1 credentialsProvider:credProvider];
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.body = [NSURL fileURLWithPath:[BBFileManager getRecordingList][0]];
uploadRequest.key = [[BBFileManager getRecordingList][0] lastPathComponent];
uploadRequest.bucket = #"bbbucket";
AWSServiceManager *serv = [AWSServiceManager defaultServiceManager];
serv.defaultServiceConfiguration = serviceConfiguration;
[AWSS3TransferManager registerS3TransferManagerWithConfiguration:serviceConfiguration forKey:#"transferKey"];
[[[AWSS3TransferManager S3TransferManagerForKey:#"transferKey"] upload:uploadRequest] continueWithBlock:^id (AWSTask *task) {
return nil;
}];
I use correct data and set right region. I try use other regions and make other stuff, but this not be helpful. I always got errors related to regions and endpoint. What I do wrong?
I've found the problem!
uploadRequest.key = [[BBFileManager getRecordingList][0] lastPathComponent];
property uploadRequest.key should contain future file path for example, if future file will be located at /bbucketname/music/IdentityId/file.mp3, value of the key should be music/IdentityId/file.mp3

Aws iOS sdk Pre-singed url giving "SignatureDoesNotMatch" error

Have problem accessing file using presigned url generated by aws sdk, given all necessary permission for the bucket.
I have downloaded the sample code from there github and changed the below
Awscredential provider as per my requirement.
The changes are below
AWSStaticCredentialsProvider *credentialsProvider =[[AWSStaticCredentialsProvider alloc] initWithAccessKey:S3AccessKey secretKey:S3secretKey];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Even though i upload the file sucessfully to aws I am not able to access them using the presigned url which i get from the aws sdk while uploading.
Can anyone point out the things i am missing in order to access the files using presigned url.
when url is loaded in browser SignatureDoesNotMatch error is shown
The most possible reason for "SignatureDoesNotMatch" is the contents in header-field are different from the one provided while generating the presigned url.
Here is a code snippet to demonstrate how to generate and download a file by using presigned url:
AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
getPreSignedURLRequest.bucket = #"bucketname";
getPreSignedURLRequest.key = #"keyname";
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodGET;
getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];
AWSS3PreSignedURLBuilder *preSignedURLBuilder = [AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder];
[[[preSignedURLBuilder getPreSignedURL:getPreSignedURLRequest] continueWithBlock:^id(BFTask *task) {
if (task.error) {
XCTAssertNil(task.error);
return nil;
}
NSURL *presignedURL = task.result;
//NSLog(#"(GET)presigned URL is: %#",presignedURL.absoluteString);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:presignedURL];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
NSError *returnError = nil;
NSHTTPURLResponse *returnResponse = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&returnResponse error:&returnError];
return nil;
}] waitUntilFinished];
The problem is with presigned url encoding. In iOS and android sdks (not in windows) you need to encode the query string in the Presigned url again.
NEWURL=baseurl +(encoded query String);
NEWURL is the correct url you can access.
it worked for me.
Try with this, you need to register PreSignedURL builder.
AWSStaticCredentialsProvider *credentialsProvider =[[AWSStaticCredentialsProvider alloc] initWithAccessKey:S3AccessKey secretKey:S3secretKey];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
// Register S3 PreSignedURL Builder
[AWSS3PreSignedURLBuilder registerS3PreSignedURLBuilderWithConfiguration:configuration forKey:#"configuration_name"];
AWSS3PreSignedURLBuilder * urlBuilder = [AWSS3PreSignedURLBuilder S3PreSignedURLBuilderForKey:#"configuration_name"];

AWS S3 SDK v2 for iOS - Download an image file to UIImage

Seems this should be relatively simple. I'm using the AWS SDK (v2) for iOS and I'm trying to download a .png file and display it to the screen in a UIImage. Everything actually works! Just very strangely...
Here is my code:
AWSStaticCredentialsProvider *credentialsProvider = [AWSStaticCredentialsProvider credentialsWithAccessKey:#"MY_ACCESS_KEY" secretKey:#"MY_SECRET_KEY"];
AWSServiceConfiguration *configuration = [AWSServiceConfiguration configurationWithRegion:AWSRegionUSWest1 credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
AWSS3 *transferManager = [[AWSS3 alloc] initWithConfiguration:configuration];
AWSS3GetObjectRequest *getImageRequest = [AWSS3GetObjectRequest new];
getImageRequest.bucket = #"MY_BUCKET";
getImageRequest.key = #"MY_KEY";
[[transferManager getObject:getImageRequest] continueWithBlock:^id(BFTask *task) {
if(task.error)
{
NSLog(#"Error: %#",task.error);
}
else
{
NSLog(#"Got image");
NSData *data = [task.result body];
UIImage *image = [UIImage imageWithData:data];
myImageView.image = image;
}
return nil;
}];
When this code gets executed, the continueWithBlock gets executed, there is no task error, so Got image is logged. And this happens fairly quickly. However, it's not until about 10 seconds later that the UIImageView updates on the screen. I even ran through the debugger to see if any of the lines following the NSLog(#"Got image"); line were taking long and they weren't. They were all executing very quickly but then the UIImageView would not be updated on the UI.
The issue is that you are updating UI component from a background thread. The continueWithBlock: block is executed in the background thread, and it is causing the aforementioned behavior. You have two options:
Use Grand Central Dispatch in the block and run it on the main thread:
...
NSURL *fileURL = [task.result body];
NSData *data = // convert fileURL to data
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:data];
myImageView.image = image;
});
...
Use mainThreadExecutor to run the block on the main thread:
[[transferManager getObject:getImageRequest] continueWithExecutor:[BFExecutor mainThreadExecutor]
withBlock:^id(BFTask *task) {
...
Hope this helps,

Resources