web-dev-qa-db-ja.com

Boto3を使用してAmazon S3にアップロードし、パブリックURLを返す

Iamは、Boto3を使用してs3にファイルをアップロードし、アップロードしたファイルを公開して、URLとして返します。

class UtilResource(BaseZMPResource):
class Meta(BaseZMPResource.Meta):
    queryset = Configuration.objects.none()
    resource_name = 'util_resource'
    allowed_methods = ['get']

def post_list(self, request, **kwargs):

    fileToUpload = request.FILES
    # write code to upload to amazone s3
    # see: https://boto3.readthedocs.org/en/latest/reference/services/s3.html


    self.session = Session(aws_access_key_id=settings.AWS_KEY_ID,
                  aws_secret_access_key=settings.AWS_ACCESS_KEY,
                  region_name=settings.AWS_REGION)

    client = self.session.client('s3')
    client.upload_file('zango-static','fileToUpload')


    url = "some/test/url"
    return self.create_response(request, {
        'url': url // return's public url of uploaded file 
    })

ドキュメント全体を検索しましたが、これを行う方法を説明するリンクを見つけることができませんでした。

24
Yaswanth Kumar

私も同じ状況です。 generate_presigned_urlを超えるBoto3のドキュメントには何も見つかりません。これは、パブリックに読み取り可能なS3オブジェクトがあるため、私の場合には必要なものではありません。

私が思いついた最高のものは:

bucket_location = boto3.client('s3').get_bucket_location(Bucket=s3_bucket_name)
object_url = "https://s3-{0}.amazonaws.com/{1}/{2}".format(
    bucket_location['LocationConstraint'],
    s3_bucket_name,
    key_name)

より良い解決策として boto3 github issues list に投稿してみてください。

34
Sam Keen

私が見つけた最良の解決策は、generate_presigned_urlを使用することですが、Client.Config.signature_versionbotocore.UNSIGNEDに設定する必要があるだけです。

次の例では、署名のないパブリックリンクが返されます。

config.signature_version = botocore.UNSIGNED
boto3.client('s3', config=config).generate_presigned_url('get_object', ExpiresIn=0, Params={'Bucket': bucket, 'Key': key})

Boto3リポジトリに関する関連する議論は次のとおりです。

10
wonton

何らかの理由でgenerate_presigned_urlの使用を回避するために、パブリックアクセス可能オブジェクトの直接URLを作成したい人、

空白と特殊文字の問題を考慮して、urllib.parse.quote_plusでURLを作成してください。

  • 私のオブジェクトキー:2018-11-26 16:34:48.351890+09:00.jpg空白と ':'に注意してください
  • AWSコンソールのS3パブリックリンク:https://s3.my_region.amazonaws.com/my_bucket_name/2018-11-26+16%3A34%3A48.351890%2B09%3A00.jpg

以下のコードは私にとっては問題ありませんでした

import boto3    
s3_client = boto3.client
bucket_location = s3_client.get_bucket_location(Bucket='my_bucket_name')
url = "https://s3.{0}.amazonaws.com/{1}/{2}".format(bucket_location['LocationConstraint'], 'my_bucket_name', quote_plus('2018-11-26 16:34:48.351890+09:00.jpg')
print(url)
2
Jay Lim