繁体   English   中英

如何生成临时 url 以使用 boto 库将文件上传到 Amazon S3?

[英]How to generate a temporary url to upload file to Amazon S3 with boto library?

我知道如何以这种方式下载文件: key.generate_url(3600)

但是当我尝试上传: key.generate_url(3600, method='PUT')时,url 不起作用。 我被告知: The request signature we calculated does not match the signature you provided. Check your key and signing method. The request signature we calculated does not match the signature you provided. Check your key and signing method.

我在boto主页上找不到有关如何使用 function generate_url(method='PUT')的示例代码。 这里有人知道如何使用它进行上传吗? 如何设置上传文件路径的参数?

我找了一些时间来试验这个,这就是我发现的。

>>> import boto
>>> c =boto.connect_s3()
>>> fp = open('myfiletoupload.txt')
>>> content_length = len(fp.read())
>>> c.generate_url(300, 'PUT', 'test-1332789015', 'foobar', headers={'Content-Length': str(content_length)}, force_http=True)
'http://test-1332789015.s3.amazonaws.com/foobar?Signature=oUARG45mR95utXsiQYRJNiCI4x4%3D&Expires=1333731456&AWSAccessKeyId=AKIAJOTCCJRP4C3NSMYA&Content-Length=16'

然后我可以使用 curl 将文件 PUT 到 url,如下所示:

$ curl --request PUT --upload-file myfiletoupload.txt "http://test-1332789015.s3.amazonaws.com/foobar?Signature=oUARG45mR95utXsiQYRJNiCI4x4%3D&Expires=1333731456&AWSAccessKeyId=AKIAJOTCCJRP4C3NSMYA&Content-Length=16"

这导致文件被上传到存储桶。 所以,看起来这是可能的。 您可能想看看是否可以计算 content-md5 值并将其包含在标头中,但您还必须弄清楚如何让 curl 也发送 header。 此外,您应该能够在 HTTPS 而不是 HTTP 上完成这项工作,但我还没有尝试过。

这是它在 boto3 中的样子(使用版本 1.2.3 测试)。

首先,使用s3.generate_presigned_url方法创建一个预签名的 url:

>>> import boto3
>>> s3 = boto3.client('s3')
>>> s3.generate_presigned_url('put_object', Params={'Bucket':'YourBucket', 'Key':'YourKey'}, ExpiresIn=3600, HttpMethod='PUT')
u'https://s3-ap-northeast-1.amazonaws.com/YourBucket/YourKey?AWSAccessKeyId=AKIAXXXXXXXXXXXXXXXX&Expires=1451061671&Signature=%2FtyAyCd5vrp13p%2FqLdoPkox7yTM%3D'

PUT 到带有预签名 URL 的 S3

$ curl \
  --request PUT \
  --upload-file path/to/file \
  "https://s3-ap-northeast-1.amazonaws.com/YourBucket/YourKey?AWSAccessKeyId=AKIAXXXXXXXXXXXXXXXX&Expires=1451061671&Signature=%2FtyAyCd5vrp13p%2FqLdoPkox7yTM%3D"

所有其他答案都假设文件将使用curl上传,这在大多数 python 脚本中确实不方便。 在下面,使用 boto3 生成预签名的boto3 ,并使用requests库上传文件:

session = boto3.Session(aws_access_key_id="XXX", aws_secret_access_key="XXX")
s3client = session.client('s3')
url = s3client.generate_presigned_url('put_object', Params={'Bucket': 'mybucket', 'Key': 'mykey'})

requests.put(url, data=open("/path/to/file").read())

这是 garnaat 在 2012 年 4 月 6 日的回答的跟进。

我正在生成一个签名的 URL 服务器端,我有凭据,并将其传递给客户端,以便客户端可以直接上传内容。 我足够信任客户端以允许它上传任意大小的文件,但不足以为其提供安全令牌。 我想避免让客户端在请求中告诉服务器其内容有多大。 因此我的后续回答。

我能够为 PUT 方法获得签名的 url,而无需在标头中指定内容长度或指定 force_http=True。

使用 Boto 2.31.1:如 garnaat 的回答:

>>> import boto
>>> c =boto.connect_s3()

然后我用了:

>>> temp_url = c.generate_url(seconds_available, 'PUT', bucket_name, s3_key)

这产生了以下形式的 url:

https://s3_location/bucket_name/s3_key?Signature=Ew407JMktSIcFln%2FZe00VroCmTU%3D&Expires=1405647669&AWSAccessKeyId=kM__pEQo2AEVd_Juz4Qq

然后我可以使用 curl 发布一个文件:

>>> os.system('curl --request PUT --upload-file true_measure/test_files/test_file_w_content.txt "'+temp_url+'"')

我确实很难弄清楚这一点,因为我通常使用python 请求来编写测试和调试; 但是,当我尝试使用它使用请求将文件放入这些 boto 生成的签名 url 之一时,我遇到了身份验证失败。 我还没有完全调试它,但我怀疑这是因为与 curl 生成的相比,请求添加了一些额外的标头。

我希望这个跟进的答案可以让其他人免于我经历的调试痛苦。

如果您使用的是 boto(不是 boto3),我能够上传的唯一方法是使用generate_url_sigv4 使用香草generate_url导致与原始问题中报告的错误相同。 可能有一个我不知道的 AWS 帐户设置控制着 function 的工作。

在带有 boto 2.49.0 和请求 2.22.0 的 Python 解释器中:

import boto
import os
import requests
os.environ['S3_USE_SIGV4'] = 'True'
c = boto.connect_s3(host='s3.amazonaws.com')
url = c.generate_url_sigv4(3600, 'PUT', 'my-bucket-name', 'bucket-path/to/file.txt')
with open('file.txt') as f:
    resp = requests.put(url, data=f.read())

>>> resp
<Response [200]>

如果您不使用主机名连接,您将在生成 URL 时收到此错误:

boto.s3.connection.HostRequiredError: BotoClientError: When using SigV4, you must specify a 'host' parameter.

有关的:
“HmacAuthV1Handler”object 没有属性“presign”是什么意思?

如果您使用的是 boto3,则预签名的 POST 似乎有更好的记录:
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html#generating-a-presigned-url-to-upload-a-file

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM