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

mic*_*luk 25 python amazon-s3 boto amazon-web-services

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

但是当我尝试上传:key.generate_url(3600,method ='PUT')时,网址无效.有人告诉我:"我们计算的请求签名与您提供的签名不符.请检查您的密钥和签名方法."

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

gar*_*aat 46

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

>>> 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'
Run Code Online (Sandbox Code Playgroud)

然后,我可以使用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"
Run Code Online (Sandbox Code Playgroud)

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

  • 此答案中的`headers`参数现在不起作用,上传时会导致'签名不匹配'错误.如果要在稍后获取文件时在响应*中指定标题*,则需要使用`response_headers`并使用诸如`response-content-type`等字段. (2认同)

qui*_*ver 27

这是它在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'
Run Code Online (Sandbox Code Playgroud)

使用预先签名的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"
Run Code Online (Sandbox Code Playgroud)

  • 感谢您在`boto3`中展示如何操作.目前正在将代码从"boto"迁移到"boto3",并希望他们的文档在所有更改中更加清晰. (2认同)

Rég*_* B. 12

所有其他答案都假设文件将被上传curl,这在大多数python脚本中真的不方便.在下面,生成一个预先签名的URL 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())
Run Code Online (Sandbox Code Playgroud)


小智 9

这是从14年4月6日开始回答garnaat的回答.

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

我能够在没有指定标题中的内容长度或指定force_http = True的情况下获取PUT方法的签名URL.

使用Boto 2.31.1:如在garnaat的回答:

>>> import boto
>>> c =boto.connect_s3()
Run Code Online (Sandbox Code Playgroud)

然后我用了:

>>> temp_url = c.generate_url(seconds_available, 'PUT', bucket_name, s3_key)
Run Code Online (Sandbox Code Playgroud)

这产生了以下形式的网址:

https://s3_location/bucket_name/s3_key?Signature=Ew407JMktSIcFln%2FZe00VroCmTU%3D&Expires=1405647669&AWSAccessKeyId=kM__pEQo2AEVd_Juz4Qq
Run Code Online (Sandbox Code Playgroud)

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

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

我确实很难解决这个问题,因为我经常使用python请求编写测试和调试; 但是,当我尝试使用它将文件放入其中一个boto生成的签名网址时,我得到了身份验证失败.我还没有完全调试过这个,但我怀疑这是因为与curl产生的相比,请求增加了一些额外的头文件.

我希望这个后续回答能够让别人感受到我经历过的调试痛苦.