7

我想使用預先簽名的URL將文件從iOS應用上傳到AWS S3存儲桶。該URL是正確的,因爲它可以在命令行上使用curl。我的代碼使用預先簽名的URL將文件上傳到AWS S3有什麼問題?

curl -v -k --upload-file FILENAME "https://MYBUCKET.amazonaws.com:443/KEYNAME?Signature=...&Expires=1391691489&AWSAccessKeyId=..." 

用下面的Objective-C代碼...

- (void)upload:(NSString *)url fileData:(NSData *)fileData 
{ 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    [request setURL:[NSURL URLWithString:url]]; 
    [request setHTTPMethod:@"PUT"]; 
    [request setHTTPBody:fileData]; 
    [request setValue:[NSString stringWithFormat:@"%d", [fileData length]] forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"audio/mpeg" forHTTPHeaderField:@"Content-Type"]; 
    [request setValue:@"public-read" forHTTPHeaderField:@"x-amz-acl"]; 
    [request setValue:@"iPhone-OS/6.0 fr_FR NE" forHTTPHeaderField:@"User-Agent"]; 

    _connection = [NSURLConnection connectionWithRequest:request delegate:self]; 
    [_connection start]; 
} 

...我得到這個錯誤:

Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x9c49560 {NSErrorFailingURLStringKey=https://MYBUCKET.s3.amazonaws.com:443/KEYNAME?Signature=...&Expires=1391703958&AWSAccessKeyId=..., NSErrorFailingURLKey=https://MYBUCKET.amazonaws.com:443/KEYNAME?Signature=...&Expires=1391703958&AWSAccessKeyId=..., NSLocalizedDescription=The request timed out., NSUnderlyingError=0x9c48c80 "The request timed out."} 

我使用Wireshark來看看是否有任何流量和有很多交通。

我不知道我的代碼有什麼問題。看來文件傳輸沒有正確終止。

+0

該文件有多大,大致需要多長時間才能傳輸? –

+0

這是5.5 MB。使用捲曲需要幾秒鐘上傳。我已經嘗試將超時設置爲120秒。但我仍然要求超時。 –

+0

你的iOS設備連接什麼類型的連接? – duskwuff

回答

9

我自己解決了這個問題。 Content-Type標題是罪魁禍首。在絕望中,我用一個非常小的文本文件測試了我的代碼,並獲得了來自S3的HTTP狀態代碼403。沒有超時。這樣的進展。如果是從客戶端的HTTP標頭中提供

<?xml version="1.0" encoding="UTF-8"?> 
<Error> 
    <Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>...</StringToSignBytes><RequestId>...</RequestId><HostId>...</HostId><SignatureProvided>...</SignatureProvided> 
    <StringToSign>PUT 

    text/plain 
    1391784394 
    KEYNAME</StringToSign> 
    <AWSAccessKeyId>...</AWSAccessKeyId> 
</Error> 

顯然,內容類型的字符串(text/plain在這種情況下)的字符串到符號被預計:我也有一個非常錯誤提示信息。不要問我爲什麼這會導致與(5.5MB?)文件超時。我希望這會爲別人節省幾個小時的生命。

最簡單的解決方法是隻刪除行

[request setValue:@"..." forHTTPHeaderField:@"Content-Type"]; 

如果你知道的內容類型,當你創建你當然可以將字符串添加到字符串到標誌則預標識的URL。

+0

你有解決GET對象,我有問題的「AccessDenied」。我正在努力爭取同樣的。 – Mrug

相關問題