2015-07-10 63 views
3

我想用Python請求(Python爲v2.7.9,請求爲v2.7)將文件上傳到Amazon S3。繼curl命令其完美的作品:如何使用Python請求在Amazon S3上執行`PUT`

curl --request PUT --upload-file img.png https://mybucket-dev.s3.amazonaws.com/6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ 

但是當我做同樣的預約,它失敗。這是我曾嘗試:

url = https://mybucket-dev.s3.amazonaws.com/6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ 
requests.put(url, files={'file': base64_encoded_image}) 
requests.put(url, files={'upload_file': base64_encoded_image}) 

它無法與403和響應我得到的是:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> 

然後我在詳細模式下運行卷曲:

* Hostname was NOT found in DNS cache 
* Trying 54.231.168.134... 
* Connected to mybucket-dev.s3.amazonaws.com (54.231.168.134) port 443 (#0) 
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
* Server certificate: *.s3.amazonaws.com 
* Server certificate: VeriSign Class 3 Secure Server CA - G3 
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5 
> PUT /6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ HTTP/1.1 
> User-Agent: curl/7.37.1 
> Host: mybucket-dev.s3.amazonaws.com 
> Accept: */* 
> Content-Length: 52369 
> Expect: 100-continue 
> 
< HTTP/1.1 100 Continue 
* We are completely uploaded and fine 
< HTTP/1.1 200 OK 
< x-amz-id-2: 5lLCQ3FVrTBg2vkyk44E+MecQJb2OGiloO0+2pKePtxPgZptKECNlUyYN43sl4LBNe9f8idh/cc= 
< x-amz-request-id: 636A24D53DEB5215 
< Date: Fri, 10 Jul 2015 12:04:44 GMT 
< ETag: "5802130d4320b56a72afe720e2c323a7" 
< Content-Length: 0 
* Server AmazonS3 is not blacklisted 
< Server: AmazonS3 
< 
* Connection #0 to host mybucket-dev.s3.amazonaws.com left intact 

於是我加入headers

headers = {'Content-Length': '52369', 'Host': 'mybucket-dev.s3.amazonaws.com', 'Expect': '100-continue', 'Accept': '*/*', 'User-Agent': 'curl/7.37.1'} 
requests.put(url, files={'file': base64_encoded_image}, headers=headers) 

我嘗試了不同的頭部組合,但它仍然拋出相同的錯誤。然後我也試着發送查詢參數:

payload={'Expires': '1436595966', 'AWSAccessKeyId': 'AQ', 'Signature': 'Ow%3D'} 
requests.put(url, files={'file': base64_encoded_image}, headers=headers, data=payload) 

它仍然失敗,同樣的錯誤。我嘗試了沒有查詢參數的URL,並將它們作爲data=payload發送到請求,但它失敗並出現相同的錯誤。

+1

任何理由,爲什麼你不能使用你的上傳'boto'? –

+0

爲什麼不使用[Boto](http://boto.readthedocs.org/en/latest/index.html)進行亞馬遜服務之間的連接和通信?使用它比使用Curl請求更容易。 – VinsanityL

+0

'boto'實例需要身份驗證,並且在我的情況下它違背了目的。我生成一個url,它是預先簽名的,任何具有該URL的人都可以執行'PUT'。他們不需要任何AWS密鑰/信用卡。現在,對於測試用例,我不想運行'os.system(curl ...',我想使用類似'requests'的庫。即使'boto'沒有憑據,我仍然想用'請求'並想知道爲什麼它失敗,作爲'捲曲'完美地工作。 – avi

回答

7

工程師requests幫我:

with open('img.png', 'rb') as data: 
    requests.put(url, data=data)