web-dev-qa-db-ja.com

botoライブラリを使用してファイルをAmazon S3にアップロードするための一時的なURLを生成するにはどうすればよいですか?

この方法でファイルをダウンロードする方法を知っていました-key.generate_url(3600)。

しかし、アップロードしようとしたとき:key.generate_url(3600、method = 'PUT')、URLが機能しませんでした。 「計算されたリクエストの署名は、提供された署名と一致しません。キーと署名方法を確認してください。」

関数generate_url(method = 'PUT')の使用方法について、botoホームページにサンプルコードが見つかりません。アップロードにそれを使用する方法を知っている人はいますか?アップロードファイルのパスのパラメーターを設定する方法

26
michael.luk

私はこれを試す時間を見つけました、そしてこれが私が見つけたものです。

>>> 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を使用して、次のようにファイルをそのURLにPUTできました。

$ 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がそのヘッダーを送信する方法も理解する必要があります。また、これをHTTPではなくHTTPSで動作させることができるはずですが、私は試していません。

46
garnaat

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'

署名付きURLを使用してS3にPUTする

$ 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"
27
quiver

他のすべての回答は、ファイルがcurlでアップロードされることを前提としています。これは、ほとんどのpythonスクリプトでは実際には不便です。以下では、boto3を使用して署名済みURLが生成されます。そして、ファイルは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())
12
Régis B.

これは、2012年4月6日からのgarnaatの回答のフォローアップです。

署名付きのURLサーバー側を生成しています。ここに資格情報があり、クライアントにコンテンツを直接アップロードできるようにそれをクライアントに渡します。クライアントを信頼して、任意のサイズのファイルをアップロードできるようにしますが、セキュリティトークンを与えるには不十分です。クライアントがコンテンツのサイズをリクエストの一部としてサーバーに伝えるのを避けたかったのです。したがって、私のフォローアップの答え。

ヘッダーでコンテンツの長さを指定したり、force_http = Trueを指定したりせずに、PUTメソッドの署名付きURLを取得できました。

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 requests を使用するため、これを理解するのは非常に困難でした。しかし、リクエストを使用してこれらのbotoが生成した署名付きURLの1つにファイルを配置しようとすると、認証エラーが発生します。私はこれを完全にデバッグしていませんが、curlが生成するものと比較してリクエストがいくつかの追加のヘッダーを追加しているためと思われます。

このフォローアップの回答が、他の誰かが私が経験したデバッグの手間を省くことを願っています。

9
user3525596

Boto3ではなくbotoを使用している場合、アップロードを機能させる唯一の方法はgenerate_url_sigv4。バニラの使用generate_urlは、元の質問で報告されたものと同じエラーを引き起こしました。どの関数が機能するかを制御するAWSアカウントの設定が不明な可能性があります。

Pythonインタプリタとboto 2.49.0および2.22.0を要求する場合:

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」オブジェクトに属性「presign」がないとはどういう意味ですか?

Boto3を使用している場合は、署名済みPOSTの方が適切に文書化されているようです:
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html#generating-a-presigned-url-to-upload-a -ファイル

0
Kenny Trytek