Saya mencoba mengunggah file ke Amazon S3 dengan Permintaan Python (Python adalah v2.7.9 dan permintaan adalah v2.7). Mengikuti perintah curl yang berfungsi dengan sempurna:
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
Namun ketika saya mencoba melakukan hal yang sama dengan permintaan, gagal dengan 403 dengan kesalahan berikut:
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
Inilah yang saya coba:
url = https://mybucket-dev.s3.amazonaws.com/6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ
headers = {'Content-Length': '52369', 'Host': 'mybucket-dev.s3.amazonaws.com', 'Expect': '100-continue', 'Accept': '*/*', 'User-Agent': 'curl/7.37.1'}
payload={'Expires': '1436595966', 'AWSAccessKeyId': 'AQ', 'Signature': 'Ow%3D'}
requests.put(url, files={'file': base64_encoded_image})
requests.put(url, files={'upload_file': base64_encoded_image})
requests.put(url, files={'file': base64_encoded_image}, headers=headers)
requests.put(url, files={'file': base64_encoded_image}, headers=headers, data=payload)
Mereka semua gagal, dengan kesalahan yang sama. Berikut curl dalam mode verbose:
* 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
Nah, langkah 1 adalah menghindari pengiriman Expect: 100 Continue
. Kami tidak menangani mereka dengan benar. Harap juga jangan mengirim tajuk Content-Length
Anda sendiri: permintaan akan melakukannya untuk Anda.
Masalah sebenarnya adalah saya pikir unggahan Anda akan dikodekan multi-bagian/formulir, tetapi curl mengunggah file secara langsung. Coba: requests.put(url, data=open('img.png', 'rb'))
Jadi, saya membuat gambar acak dan melakukannya
curl --request PUT --upload-file img.png https://httpbin.org/put
Untuk memverifikasi bahwa curl melakukan persis seperti yang saya harapkan (yang dilakukannya). Ini mengunggah file sebagai data mentah.
Parameter files=
dalam permintaan mengupload multipart/form-data
, bukan mengupload data mentah. Untuk mereplikasi perilaku yang sama dalam permintaan, yang perlu Anda lakukan adalah sebagai berikut:
with open('img.png', 'rb') as data:
requests.put(url, data=data)
Permintaan akan menangani pengaturan panjang konten dan yang lainnya.
bekerja! Terima kasih banyak teman-teman :dancer: :senyum:
Dengan menggunakan mencoba file Zip saya mendapatkan yang berikut, petunjuk apa pun: (requests-2.13.0)
with open('default.zip', 'rb') as data:
requests.put(url, data=data)
Keluaran:
C:\svn\libraries\cpp>python req_put.py default.zip
MD5: 5dc0658d93e942fa7d1fa443e04bba83
SHA1: 18e7980d9d9ac544ac3e684a4d051932c3a3a336
Traceback (most recent call last):
File "req_put.py", line 102, in <module>
resp = requests.put(uri, headers=headers, data=data) # data=data , params=payload)
File "C:\Python27\lib\site-packages\requests\api.py", line 124, in put
return request('put', url, data=data, **kwargs)
File "C:\Python27\lib\site-packages\requests\api.py", line 56, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 488, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 609, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests\adapters.py", line 473, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', error(10054, 'An existing connection was forcibly closed by the remote host'))
Komentar yang paling membantu
Jadi, saya membuat gambar acak dan melakukannya
Untuk memverifikasi bahwa curl melakukan persis seperti yang saya harapkan (yang dilakukannya). Ini mengunggah file sebagai data mentah.
Parameter
files=
dalam permintaan menguploadmultipart/form-data
, bukan mengupload data mentah. Untuk mereplikasi perilaku yang sama dalam permintaan, yang perlu Anda lakukan adalah sebagai berikut:Permintaan akan menangani pengaturan panjang konten dan yang lainnya.