Vla*_*lad 1 amazon-s3 amazon-web-services afnetworking afnetworking-2
我正在尝试将图像从我的iPhone应用程序上传到S3,然后将S3网址存储回我的rails应用程序.我不应该在iOS应用程序中嵌入凭据,所以我采取的方法是:
aws-sdk
gem生成并返回预先签名的URL 如何在S3中存储数据并允许用户使用rails API/iOS客户端以安全的方式访问?我尽力遵循我在网上找到的所有指示,但它不起作用,步骤3的结果返回错误401禁止.由于我是新手,我甚至不知道我做错了什么.
在第2步中,我的代码如下所示:
def getS3Url
s3 = AWS::S3.new(
:access_key_id => "MY S3 KEY",
:secret_access_key => "MY SECRET ACCESS KEY"
)
object = s3.buckets[params["bucket"]].objects[params["path"]]
@s3url = object.url_for(:write, { :expires => 20.minutes.from_now, :secure => true }).to_s
end
Run Code Online (Sandbox Code Playgroud)
从step2返回的url看起来像这样: https://s3.amazonaws.com/myapp-bucket-name/images/avatar/user1.png?AWSAccessKeyId=[access key id]&Expires=[expiration timestamp]&Signature=[Signature]
一旦我得到该URL,我尝试通过执行以下操作发布到它:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:[responseObject valueForKey:@"s3url"] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:jpegData name:@"file" fileName:self.filename mimeType:@"image/png"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
Run Code Online (Sandbox Code Playgroud)
在这段代码中,我从返回的对象中提取出url [responseObject valueForKey:@"s3url"]
,然后将其作为要发布的URL传递.但它不起作用.这是我在XCode中运行时的日志:
错误:错误域= AFNetworkingErrorDomain代码= -1011"请求失败:禁止(403)"UserInfo = 0x156daaf0 {NSErrorFailingURLKey = https://s3.amazonaws.com/myapp-bucket-name/images/avatar/user1.png?AWSAccessKeyId = [access key id]&Expires = [expiration timestamp]&Signature = [Signature],NSLocalizedDescription = Request failed:forbidden(403),NSUnderlyingError = 0x156aef90"Request failed:unacceptable content-type:application/xml",AFNetworkingOperationFailingURLResponseErrorKey = {URL:https://s3.amazonaws.com/myapp-bucket-name/images/avatar/user1.png?AWSAccessKeyId=[access key id]&Expires = [expiration timestamp]&Signature = [Signature]} {status code:403,headers {Connection = close; "Content-Type"="application/xml"; Date ="Mon,30 Jun 2014 07:21:33 GMT"; Server = AmazonS3; "转移编码"=身份; "x-amz-id-2"="FJwEeOjV1/osJKgKeHO +/OjXVBEbvW09XxNX2kn1UYIuHswU + LKh0mJODRJDNLXm"; "x-amz-request-id"= 46E84D0967B6D4CD; }}}
在这一点上,我甚至不知道我做错了什么.也许我甚至没有发布到正确的URL.也许我需要做的不仅仅是POST.我花了整个周末试图解决这个问题而失败了.有人可以帮忙吗?谢谢.
我遇到了类似的"挑战".我必须使用AFNetworking 2.0将图像上传到带有来自我服务器的预签名URL的S3存储桶.在我的许多尝试和错误尝试之一,我得到了相同的403错误,发生在我身上的是我必须在请求中放置正确的标头:
Content-Type
使用mime类型的图像x-amz-acl
至于public-read
我的水桶配置Content-Length似乎是可选的,请注意我没有在multipart中上传图像.
所以这就是我最终做的事情:
+(void) uploadImage:(UIImage *)image atUrl:(NSString *)url withMimeType:(NSString *)mimeType withSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure {
NSData *imageData = UIImageJPEGRepresentation(image, 0.1);
NSURL *requestURL = [NSURL URLWithString:url];
AFHTTPSessionManager *client = [[AFHTTPSessionManager alloc] initWithBaseURL:requestURL];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"PUT"];
[request setValue:mimeType forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:imageData];
[request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[imageData length]] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"public-read" forHTTPHeaderField:@"x-amz-acl"];
[request setURL:requestURL];
NSURLSessionDataTask *task = [client dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error == nil) {
if (success) {
success(responseObject);
}
} else {
if (failure) {
failure(error);
}
}
}];
[task resume];
}
Run Code Online (Sandbox Code Playgroud)
url是我从服务器获得的预签名网址.检查我在0.1的JPEG压缩,因为您可能需要不同的压缩.在我看来,图像质量并不重要.
归档时间: |
|
查看次数: |
2956 次 |
最近记录: |