ios upload file to amazon s3 - ios

I am working on an ios app that needs to be able to upload files to amazon s3 but I am having some issues. The function manages to create the correct key or path within the s3 bucket but the file itself does not upload into it. below is the code for 1 of the options i have tried
if (self.s3 == nil) {
self.s3 = [[AmazonS3Client alloc] initWithAccessKey:[Config getS3Key] withSecretKey:[Config getS3Secret]] ;
}
[self performSelectorInBackground:#selector(processBackgroundThreadUploadInBackground:)
withObject:params];
}
- (void)processBackgroundThreadUploadInBackground:(NSMutableDictionary *)params
{
S3PutObjectRequest *por = [[S3PutObjectRequest alloc] initWithKey:#"staging/videos/" inBucket:#"aaa.aaaaa.com"];
por.contentType = #"video/mp4";
por.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[params valueForKey:#"takeurl"]]];
// por.contentType = #"image/png";
// por.data = [params valueForKey:#"takeimage"];
S3PutObjectResponse *putObjectResponse = [self.s3 putObject:por];
[self performSelectorOnMainThread:#selector(showCheckErrorMessage:)
withObject:putObjectResponse.error
waitUntilDone:NO];
}
this creates the key path staging/videos/ within the bucket on s3 but the file is not there. I tried this with an image file also. I have checked to make sure that the data that i am trying to push up is not nil.
The xml response i get from the server says that the content length is 0 though.
I have also tried the multi part approach from the s3 sdk with the same result.
Can anyone see what I am doing wrong ?

I'm obviously really late with this response, but just in case anyone else has this problem in the future, you were structuring your request wrong.
By doing:
S3PutObjectRequest *por = [[S3PutObjectRequest alloc] initWithKey:#"staging/videos/" inBucket:#"aaa.aaaaa.com"];
with a backslash at the end of your key, you were creating a folder, not a file. You need to end your key with the filename including a suffix, ex #"staging/videos/video.mp4".

Related

iOS AWS SDK overrides the Content-Type property

I am trying to set the Content-Type property of my file as follows but when I inspect the file in the web, the content-type is reset to application/octet-stream
S3PutObjectRequest *request = [[S3PutObjectRequest alloc] initWithKey:key inBucket:bucket];
request.filename = filePath;
request.contentType = [self mimeTypeForFileAtPath:operation.filePath]; //Returns #"image/jpeg"
operation.operation = [self.manager upload:request];
At the filepath resides a NSData written to a file with a UUID as filename (no file extension).
Any leads would be appreciated
I have found a workaround for this problem. Instead of providing the filename, I proved the data to the S3PutObjectRequest
request.data = [NSData dataWithContentsOfFile:operation.filePath];
request.contentType = [self mimeTypeForFileAtPath:operation.filePath];

AWS iOS SDK v2 Files Upload to S3 issue

I am trying to upload images to the S3, and for files that are less than 2 mb, it is ok, but for more than 2 mb, server return Code=-1001 "The request timed out.". Could someone explain how it is possible to handle this problem?
Code example below:
AWSS3 *s3 = [[AWSS3 alloc] initWithConfiguration:configuration];
AWSS3PutObjectRequest *logFile = [AWSS3PutObjectRequest new];
logFile.bucket = bucket;
logFile.key = path;
logFile.contentType = [self contentTypeForImageData:self.userPicture];
logFile.body = self.userPicture;
logFile.contentLength = [NSNumber numberWithInteger:[self.userPicture length]];
[[s3 putObject:logFile] continueWithBlock:^id(BFTask *task) {
NSLog(#"Amazon error : %#", [task error]);
return nil;
}];
When using initWithConfiguration:, you must manually retain a strong reference to an instance of AWSS3. One way to accomplish this is to make it a property. Using defaultS3 eliminates the need for this since the AWSS3 class retains the strong reference to the default service client for you.
Hope this helps,

UICollectionView: get profile pictures from Instagram instead of recent media pictures to display

I am a newbie iOS learner. Couldn't find answer to following question after searching for a while. Hence, here it is.
Building on a first app that displays recent pictures from a user's instagram feed, I am trying to display pictures from the follows of that users instead.
To call recent pictures from the Instagram feed, which worked well, I had created the following method "imageForPhoto"
+ (void)imageForPhoto:(NSDictionary *)photo size:(NSString *)size completion:(void(^)(UIImage *image))completion {
if (photo == nil || size == nil || completion == nil) {
return;
}
NSString *key = [[NSString alloc] initWithFormat:#"%#-%#", photo[#"id"], size];
NSURL *url = [[NSURL alloc] initWithString:photo[#"images"][size][#"url"]];
[self downloadURL:url key:key completion:completion];
}
Therefore, I first modified my code to get the data related to the "follows" in my PhotosViewController instead of recent media pictures ( v1/users/3/follows ):
NSURLSession *session = [NSURLSession sharedSession];
NSString *urlString = [[NSString alloc] initWithFormat:#"https://api.instagram.com/v1/users/3/follows?count=99&access_token=%#", self.accessToken];
Then, I created a new method that I called friendAvatarForPhoto to get the follows profile pictures from a photo NSDictionary that is passed in as the only method parameter. I placed this method in my PhotoController class:
+ (void)friendAvatarForPhoto:(NSDictionary *)photo completion:(void(^)(UIImage *image))completion {
if (photo == nil || completion == nil) {
return;
}
NSString *key = [[NSString alloc] initWithFormat:#"avatar-%#", photo[#"user"][#"id"]];
NSURL *url = [[NSURL alloc] initWithString:photo[#"profile_picture"]];
[self downloadURL:url key:key completion:completion];
}
It seems to work. I have manually checked that the pictures that are rendered on my UICollectionView are actually coming from the "profile_picture" key of the responseDictionary I get back from Instagram.
Here is the structure of this dictionary: https://www.dropbox.com/s/ldjqupadqg0j3nq/friends_response_dictionary.png
Specifically, as you can see, I modified both the key and the url:
NSString *key = [[NSString alloc] initWithFormat:#"avatar-%#", photo[#"user"][#"id"]];
NSURL *url = [[NSURL alloc] initWithString:photo[#"profile_picture"]];
but I am not really understanding what I need to initial the *key string with... I kept "avatar" for example but why should I? I am pretty sure it's wrong although the result seems to be fine from what is returned on my UICollectionView.
What should I initiate this string with instead?
What is the function of this key in the overall NSURLSession process?
I'd love to better understand the overall process and better connect the dots with Instagram's API so I can query the right key and be sure I am getting what I am looking for. In a reliable way, not an intuitive one as I have just done app-arently.
Any help from experienced developers in the community would be welcome, I've just started to explore iOS dev a few weeks ago based on rusty C skills from a long time back.
Thank you!
:) Arsene

Xcode with VFR Reader loading PDF mistake

I use vfr/reader to open PDF files. When I open first PDF file my app opens it correctly but when I open another one, my app opens the first file again.
This is my function to read PDF file
-(void)readIssue:(IssueMath *)issue {
NSString *filePath = [[issue.contentURL path] stringByAppendingPathComponent:#"Mathematics.pdf"];
NSLog(#"Read Path 1: %# ",filePath);
ReaderDocument *document = [ReaderDocument withDocumentFilePath:filePath password:nil];
NSLog(#"Read Path 2: %# ",document.fileURL);
ReaderViewController *readerViewController = [[ReaderViewController alloc] initWithReaderDocument:document];
readerViewController.delegate = self; // Set the ReaderViewController delegate to self
readerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
readerViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentModalViewController:readerViewController animated:YES];
}
And this is NSLog output:
2012-11-02 20:09:31.081 MAGAZINE[314:15203] Read Path 1: /Users/eakmotion/Library/Application Support/iPhone Simulator/5.0/Applications/EC25BC08-E1E7-44B6-9AD8-0A321EEAC8B6/Library/Caches/ISSUE3_2011/Mathematics.pdf
2012-11-02 20:09:31.109 MAGAZINE[314:15203] Read Path 2: file://localhost/Users/eakmotion/Library/Application%20Support/iPhone%20Simulator/5.0/Applications/EC25BC08-E1E7-44B6-9AD8-0A321EEAC8B6/Library/Caches/ISSUE2_2011/Mathematics.pdf
I want to read "ISSUE3_2011/Mathematics.pdf" but app still reads first path "ISSUE2_2011/Mathematics.pdf"
Why filePath is still the same?
How can I solve this problem?
Yeah your solution works but if you want to keep track of your all pdf documents (ex. current page no)
You have to give unique names for your local pdf files.. Because it will search for Mathematics.plist file on local device folder to read the current page number..
/Users/eakmotion/Library/Application Support/iPhone Simulator/5.0/Applications/EC25BC08-E1E7-44B6-9AD8-0A321EEAC8B6/Library/Caches/ISSUE3_2011/Mathematics.pdf
file://localhost/Users/eakmotion/Library/Application%20Support/iPhone%20Simulator/5.0/Applications/EC25BC08-E1E7-44B6-9AD8-0A321EEAC8B6/Library/Caches/ISSUE2_2011/Mathematics.pdf
these files are looking for the same Mathematics.plist file
in the class ReaderDocument "unarchiveFromFileName" method
NSString *archivePath = [ReaderDocument applicationSupportPath]; // Application's "~/Library/Application Support" path
NSString *archiveName = [[filename stringByDeletingPathExtension] stringByAppendingPathExtension:#"plist"];
try to modify this code section or give your files unique names like Mathematics_ISSUE3_2011.pdf and Mathematics_ISSUE2_2011.pdf
I know this question is quite a few months old, but just in case anyone is experiencing this same issue (as myself), I have found a solution for it.
In the vfr/Reader's source, locate the Sources/ReaderDocument.m file, and look for a function named + (ReaderDocument *)withDocumentFilePath:.
There, comment out the conditional which prevents the document from reloading as shown below.
+ (ReaderDocument *)withDocumentFilePath:(NSString *)filePath password:(NSString *)phrase
{
ReaderDocument *document = nil; // ReaderDocument object
document = [ReaderDocument unarchiveFromFileName:filePath password:phrase];
//if (document == nil) // Unarchive failed so we create a new ReaderDocument object
//{
document = [[ReaderDocument alloc] initWithFilePath:filePath password:phrase];
//}
return document;
}
This was my quick and dirty approach to get documents to reload. The caveat to this solution is that the pdf reader won't keep track of where you left off in your pdf pages, which in my app, was not of importance.
I was facing the same problem and found following solution:
// Path to first PDF file
NSString *filePath =
[[NSBundle mainBundle] pathForResource:#"someBookeName" ofType:#"pdf"];
Just change the file path like shown above. As you can see, now you don't need NSArray * PDF.

Amazon AWS IOS SDK: How to download ALL files in a bucket without naming them individually

I upload and download files from AWS S3. Trouble is, I am having to specify each file by its name. I want to be able to download all the files in a specific bucket (directory) without naming them individually.
I currently use this code:
s3Client = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY withSecretKey:SECRET_KEY];
getObjectRequest = [[S3GetObjectRequest alloc] initWithKey:arrayName withBucket:bucketName];
getObjectResponse = [s3Client getObject:getObjectRequest];
S3ListObjectsRequest *listObjectRequest = [[[S3ListObjectsRequest alloc] initWithName:"YourBucket"] autorelease];
S3ListObjectsResponse *listObjectResponse = [[AmazonClientManager s3] listObjects:listObjectRequest];
S3ListObjectsResult *listObjectsResults = listObjectResponse.listObjectsResult;
for (S3ObjectSummary *objectSummary in listObjectsResults.objectSummaries) {
NSLog(#"Bucket Contents %# " ,[objectSummary key]);
}

Resources