我在这个问题上大发雷霆……我正在使用 ASIHTTPRequest ( http://allseeing-i.com/ASIHTTPRequest/ ) 包装库来访问 Amazon S3 存储。我能够很好地连接并获取存储桶列表而没有任何问题。我的挫败感是尝试将新对象(照片)上传(PUT 和/或 POST)到现有存储桶。我正在关注亚马逊的文件,(至少我认为我是。)但似乎没有任何效果。
在我跳出窗户之前,请有人帮助我。我不想死。:-(
提前感谢我能得到的任何帮助。
L.
我在这个问题上大发雷霆……我正在使用 ASIHTTPRequest ( http://allseeing-i.com/ASIHTTPRequest/ ) 包装库来访问 Amazon S3 存储。我能够很好地连接并获取存储桶列表而没有任何问题。我的挫败感是尝试将新对象(照片)上传(PUT 和/或 POST)到现有存储桶。我正在关注亚马逊的文件,(至少我认为我是。)但似乎没有任何效果。
在我跳出窗户之前,请有人帮助我。我不想死。:-(
提前感谢我能得到的任何帮助。
L.
这是一个使用 PUT 的基本示例。显然,您应该在现实世界中使用队列而不是同步请求。
如果您更改 amz 标头,请不要忘记按照 Amazon 的说明更新“canonicalizedAmzHeaders”。
#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];
}
如果它对任何发现这个问题的人有帮助 - 现在 ASIHTTPRequest 中内置了基本 S3 支持:
http://allseeing-i.com/ASIHTTPRequest/S3
我一直在考虑添加 S3 支持很长时间了,但是你的问题把它推到了队列的前面:)
看起来亚马逊现在有一个 iOS SDK,目前(2011 年 4 月)处于测试阶段: http: //aws.amazon.com/sdkforios/。
还有Connection Kit Cocoa 框架,它能够将数据上传到不同的服务,包括 Amazon S3。我很确定它的源代码为您提供了一些起点。