Requests: `PUT` 到 Amazon S3 失败

创建于 2015-07-10  ·  4评论  ·  资料来源: psf/requests

我正在尝试使用 Python 请求(Python 为 v2.7.9,请求为 v2.7)将文件上传到 Amazon S3。 遵循完美运行的 curl 命令:

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

但是,当我尝试对请求执行相同操作时,它失败并显示 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>

这是我尝试过的:

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)

他们都失败了,有同样的错误。 这是详细模式下的 curl:

* 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

最有用的评论

所以,我做了一个随机图像并做了

curl --request PUT --upload-file img.png https://httpbin.org/put

验证 curl 是否完全符合我的预期(确实如此)。 它将文件作为原始数据上传。

请求中的files=参数执行multipart/form-data上传,而不是原始数据上传。 要在请求中复制相同的行为,您只需执行以下操作:

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

请求将处理设置内容长度和其他一切。

所有4条评论

好吧,第 1 步是避免发送Expect: 100 Continue 。 我们没有妥善处理它们。 也请不要发送您自己的Content-Length标头:请求会为您做到这一点。

真正的问题是我认为您的上传将是多部分/表单编码的,但 curl 是直接上传文件。 试试: requests.put(url, data=open('img.png', 'rb'))

所以,我做了一个随机图像并做了

curl --request PUT --upload-file img.png https://httpbin.org/put

验证 curl 是否完全符合我的预期(确实如此)。 它将文件作为原始数据上传。

请求中的files=参数执行multipart/form-data上传,而不是原始数据上传。 要在请求中复制相同的行为,您只需执行以下操作:

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

请求将处理设置内容长度和其他一切。

作品! 非常感谢你们 :dancer:: :smile:

通过尝试使用 zip 文件,我得到以下任何线索:(requests-2.13.0)

with open('default.zip', 'rb') as data:
    requests.put(url, data=data)

输出:

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'))

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

NoahCardoza picture NoahCardoza  ·  4评论

cnicodeme picture cnicodeme  ·  3评论

thadeusb picture thadeusb  ·  3评论

iLaus picture iLaus  ·  3评论

ReimarBauer picture ReimarBauer  ·  4评论