2012-04-06 9 views
19

私はこの方法でファイルをダウンロードする方法を知っていました--key.generate_url(3600)。botoライブラリを使用してAmazon S3にファイルをアップロードするための一時URLを生成するにはどうすればよいですか?

アップロードしようとしたときに、key.generate_url(3600、method = 'PUT')、URLが機能しませんでした。私は言った: "私たちが計算した要求の署名があなたが提供した署名と一致しません。鍵と署名の方法を確認してください。

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

+0

は、その新たなファイルですか?新しいファイルを作成するには、 'PUT'ではなく' POST'を使うべきです。 – vartec

+0

@vartec: "新しいファイル"とはどういう意味ですか?私の使用例では、あるキーに新しいキーをアップロードする必要があることがあります。古いキーを上書きする必要があることがあります。だから私は 'PUT'と 'POST'のコード例が必要だと思う。 –

答えて

40

私はこのことを試してみるまでに時間がありましたが、ここに私が見つけたものがあります。

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

私は、このようにその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の値を計算してヘッダーに含めることができるかどうかを見たいかもしれませんが、カールを取得してそのヘッダーを送信する方法も把握する必要があります。また、HTTPではなくHTTPS経由でこの作業を行うことができるはずですが、私はそれを試していません。

+0

これは動作します、ありがとう! –

+2

この回答の 'headers'引数は動作しません。アップロードすると 'signature mismatch'エラーが発生します。後でファイルを取得するときに、レスポンスにヘッダー*を指定する場合は、 'response_headers'を使用し、' response-content-type'などのフィールドを使用する必要があります。 – MLister

+0

Google Cloud Storageでテストされましたが失敗しました。この質問を見てもらえますか?ありがとう。 http://stackoverflow.com/questions/38938203/django-heroku-boto-direct-file-upload-to-google-cloud-storage –

8

これは、4月6日からのガーナートの回答に対するフォローアップです。

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

ヘッダーにコンテンツの長さを指定したり、force_http = Trueを指定することなく、PUTメソッドの署名付きURLを取得できました。 garnaatのanswereのように :

>>> 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 
後のBoto 2.31.1を使用して

私はカールを使ってファイルを投稿することができました:

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

私は通常、python requestsを使ってテストとデバッグを行うので、これを理解するのは非常に困難でした。しかし、私は認証失敗を取得しようとすると、私はそれを使用して、これらのbotoのいずれかにリクエストを使って署名付きURLを生成しました。私はこれを完全にデバッグしていませんが、curlが生成するものと比べてリクエストがいくつか追加されていると思われます。

このフォローアップの回答は、他の誰かが私が経験したデバッグの苦労を惜しみなく願っています。

17

boto3(バージョン1.2.3でテスト済み)の外観は次のとおりです。

まず、s3.generate_presigned_url方法でpresigned URLを作成します。他のすべての答えは、ファイルがある、curlでアップロードされると仮定しpresigned URLとS3へ

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

$ 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" 
+0

どのようにあなたの認証情報、すなわちAWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEYを追加しますか? – CpILL

+1

@CpILL資格情報を環境変数で渡すことができます。例:$ export AWS_ACCESS_KEY_ID = AKIAIOSFODNN7EXAMPLE http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment – quiver

+0

素晴らしい回答、ありがとう! –

9

ほとんどの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()) 
関連する問題