私は現在アマゾンS3に画像をアップロードしているアプリがあります。 NSURLConnectionからNSURLSessionへの切り替えを試みているので、アプリがバックグラウンドにある間にアップロードを続けることができます!私はちょっとした問題にぶつかっているようだ。 NSURLRequestが作成され、NSURLSessionに渡されますが、ファイルを完全にアップロードするNSURLConnectionに同じリクエストを渡すと、amazonは403 - 禁止された応答を返します。ここでNSURLSessionとamazon S3のアップロード
はレスポンスを作成するコードです:
NSString *requestURLString = [NSString stringWithFormat:@"http://%@.%@/%@/%@", BUCKET_NAME, AWS_HOST, DIRECTORY_NAME, filename];
NSURL *requestURL = [NSURL URLWithString:requestURLString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:60.0];
// Configure request
[request setHTTPMethod:@"PUT"];
[request setValue:[NSString stringWithFormat:@"%@.%@", BUCKET_NAME, AWS_HOST] forHTTPHeaderField:@"Host"];
[request setValue:[self formattedDateString] forHTTPHeaderField:@"Date"];
[request setValue:@"public-read" forHTTPHeaderField:@"x-amz-acl"];
[request setHTTPBody:imageData];
そしてこれは、応答(私はこれがSO答える他から来たと思います)に署名:私はこのラインを使用する場合は、
NSString *contentMd5 = [request valueForHTTPHeaderField:@"Content-MD5"];
NSString *contentType = [request valueForHTTPHeaderField:@"Content-Type"];
NSString *timestamp = [request valueForHTTPHeaderField:@"Date"];
if (nil == contentMd5) contentMd5 = @"";
if (nil == contentType) contentType = @"";
NSMutableString *canonicalizedAmzHeaders = [NSMutableString string];
NSArray *sortedHeaders = [[[request allHTTPHeaderFields] allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
for (id key in sortedHeaders)
{
NSString *keyName = [(NSString *)key lowercaseString];
if ([keyName hasPrefix:@"x-amz-"]){
[canonicalizedAmzHeaders appendFormat:@"%@:%@\n", keyName, [request valueForHTTPHeaderField:(NSString *)key]];
}
}
NSString *bucket = @"";
NSString *path = request.URL.path;
NSString *query = request.URL.query;
NSString *host = [request valueForHTTPHeaderField:@"Host"];
if (![host isEqualToString:@"s3.amazonaws.com"]) {
bucket = [host substringToIndex:[host rangeOfString:@".s3.amazonaws.com"].location];
}
NSString* canonicalizedResource;
if (nil == path || path.length < 1) {
if (nil == bucket || bucket.length < 1) {
canonicalizedResource = @"/";
}
else {
canonicalizedResource = [NSString stringWithFormat:@"/%@/", bucket];
}
}
else {
canonicalizedResource = [NSString stringWithFormat:@"/%@%@", bucket, path];
}
if (query != nil && [query length] > 0) {
canonicalizedResource = [canonicalizedResource stringByAppendingFormat:@"?%@", query];
}
NSString* stringToSign = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n%@%@", [request HTTPMethod], contentMd5, contentType, timestamp, canonicalizedAmzHeaders, canonicalizedResource];
NSString *signature = [self signatureForString:stringToSign];
[request setValue:[NSString stringWithFormat:@"AWS %@:%@", self.S3AccessKey, signature] forHTTPHeaderField:@"Authorization"];
をコードの:
[NSURLConnection connectionWithRequest:request delegate:self];
それが動作し、ファイルをアップロードし、私が使用している場合:
NSURLSessionUploadTask *task = [self.session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:filePath]];
[task resume];
私は禁じられたエラーを受け取ります..!?
誰もがこれを使ってS3にアップロードしようとしましたが、同様の問題が発生しましたか?セッションが一時停止してアップロードを再開する方法と関係があるのだろうか、それともリクエストに面白い何かをしているのだろうか?
可能な解決策の1つは、私が管理している暫定的なサーバーにファイルをアップロードして、それが完了したらS3に転送することです。これは明らかに理想的な解決策ではありません。
ご迷惑をおかけして申し訳ありません。
ありがとうございます!
@ GeogeGreen私はアップロードする必要があります大容量の動画をs3バケツに変換すると、おそらく5GBになるでしょう。NSURLSessionを使ってそれを行うことができます。私が読んだものは、バックグラウンドセッションは長時間実行されません。 –