I am pulling my hair out on this one... I am using the ASIHTTPRequest (http://allseeing-i.com/ASIHTTPRequest/) wrapper library for accessing Amazon S3 storage. I am able to connect just fine and grab a listing of buckets without any problems. My frustration is with trying to UPLOAD (PUT and/or POST) a new object (a photo) to an existing bucket. I am following Amazon's documentation to the letter, (at least I think I am.) but nothing seems to work.
Please, someone help me before I jump out of a window. I don't want to die. :-(
Thanks in advance for ANY help I can get.
L.
To upload folders and files to an S3 bucketSign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/ . In the Buckets list, choose the name of the bucket that you want to upload your folders or files to. Choose Upload.
When you upload large files to Amazon S3, it's a best practice to leverage multipart uploads. If you're using the AWS Command Line Interface (AWS CLI), then all high-level aws s3 commands automatically perform a multipart upload when the object is large. These high-level commands include aws s3 cp and aws s3 sync.
In the Amazon S3 console, choose the bucket where you want to upload an object, choose Upload, and then choose Add Files. In the file selection dialog box, find the file that you want to upload, choose it, choose Open, and then choose Start Upload. You can watch the progress of the upload in the Transfer pane.
Here is a basic example using PUT. Obviously you should be using a queue rather than a synchronous request in the real world.
If you change the amz headers, don't forget to update 'canonicalizedAmzHeaders' as per Amazon's instructions.
#import "ASIHTTPRequest.h"
#import <CommonCrypto/CommonHMAC.h>
...
- (void)testS3
{
NSString *filePath = @"/path/to/file";
NSString *contentType = @"text/plain";
NSString *bucket = @"mybucket";
NSString *path = @"test";
NSString *secretAccessKey = @"my-secret-access-key";
NSString *accessKey = @"my-access-key";
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzzz"];
NSString *date = [dateFormatter stringFromDate:[NSDate date]];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.s3.amazonaws.com/%@",bucket,path]]] autorelease];
[request setPostBodyFilePath:filePath];
[request setShouldStreamPostDataFromDisk:YES];
[request setRequestMethod:@"PUT"];
[request addRequestHeader:@"x-amz-acl" value:@"private"];
[request addRequestHeader:@"Content-Type" value:contentType];
[request addRequestHeader:@"Date" value:date];
NSString *canonicalizedAmzHeaders = @"x-amz-acl:private";
NSString *canonicalizedResource = [NSString stringWithFormat:@"/%@/%@",bucket,path];
NSString *stringToSign = [NSString stringWithFormat:@"PUT\n\n%@\n%@\n%@\n%@",contentType,date,canonicalizedAmzHeaders,canonicalizedResource];
NSString *signature = [self base64forData:[self HMACSHA1withKey:secretAccessKey forString:stringToSign]];
NSString *auth = [NSString stringWithFormat:@"AWS %@:%@",accessKey,signature];
[request addRequestHeader:@"Authorization" value:auth];
[request start];
NSLog(@"%@",[request responseString]);
}
// Source: http://stackoverflow.com/questions/476455/is-there-a-library-for-iphone-to-work-with-hmac-sha-1-encoding
- (NSData *)HMACSHA1withKey:(NSString *)key forString:(NSString *)string
{
NSData *clearTextData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
CCHmacContext hmacContext;
CCHmacInit(&hmacContext, kCCHmacAlgSHA1, keyData.bytes, keyData.length);
CCHmacUpdate(&hmacContext, clearTextData.bytes, clearTextData.length);
CCHmacFinal(&hmacContext, digest);
return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
}
//Source http://www.cocoadev.com/index.pl?BaseSixtyFour
- (NSString *)base64forData:(NSData *)data
{
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if ([data length] == 0)
return @"";
char *characters = malloc((([data length] + 2) / 3) * 4);
if (characters == NULL)
return nil;
NSUInteger length = 0;
NSUInteger i = 0;
while (i < [data length])
{
char buffer[3] = {0,0,0};
short bufferLength = 0;
while (bufferLength < 3 && i < [data length])
buffer[bufferLength++] = ((char *)[data bytes])[i++];
// Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
if (bufferLength > 1)
characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
else characters[length++] = '=';
if (bufferLength > 2)
characters[length++] = encodingTable[buffer[2] & 0x3F];
else characters[length++] = '=';
}
return [[[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES] autorelease];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With