使用 Boto3 和 return public url 上传到 Amazon S3

Upload to Amazon S3 using Boto3 and return public url

我正在尝试使用 Boto3 将文件上传到 s3,并将上传的文件 public 和 return 作为 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 
    })

我搜索了整个文档,但找不到任何描述如何执行此操作的链接,有人可以解释或提供任何我可以找到答案的资源吗?

我也是这种情况。 无法在 generate_presigned_url 之外的 Boto3 文档中找到任何内容,这不是我所需要的,因为我有 public 可读的 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 上发帖以获得更好的解决方案。

我遇到了同样的问题。 假设您知道要存储数据的存储桶名称,则可以使用以下命令:

import boto3
from boto3.s3.transfer import S3Transfer

credentials = { 
    'aws_access_key_id': aws_access_key_id,
    'aws_secret_access_key': aws_secret_access_key
}

client = boto3.client('s3', 'us-west-2', **credentials)
transfer = S3Transfer(client)

transfer.upload_file('/tmp/myfile', bucket, key,
                     extra_args={'ACL': 'public-read'})

file_url = '%s/%s/%s' % (client.meta.endpoint_url, bucket, key)

我找到的最好的解决方案仍然是使用generate_presigned_url,只是Client.Config.signature_version需要设置为botocore.UNSIGNED

下面returns public link 没有签名的东西。

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

boto3 存储库上的相关讨论是:

对于 Django,如果您将 Django 存储与 boto3 一起使用,则下面的代码完全符合您的要求:

default_storage.url(name=f.name)

想要为 public 可访问对象构建直接 URL 以避免出于某种原因使用 generate_presigned_url 的人。

考虑到空格和特殊字符问题,请使用 urllib.parse.quote_plus 构建 URL。

  • 我的对象键:2018-11-26 16:34:48.351890+09:00.jpg 请注意空格和“:”
  • S3 public link 在 aws 控制台中: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)

我用了一个 f-string 作为相同的

import boto3    
#s3_client = boto3.session.Session(profile_name='sssss').client('s3')
s3_client=boto3.client('s3')
s3_bucket_name = 'xxxxx'
s3_website_URL= f"http://{s3_bucket_name}.s3-website.{s3_client.get_bucket_location(Bucket=s3_bucket_name)['LocationConstraint']}.amazonaws.com"

通过现有的答案和他们的评论,我做了以下并且适用于文件名的特殊情况,例如具有 空格 ,具有 特殊字符( ASCII)极端情况。例如。格式的文件名:“key=value.txt”

import boto3
import botocore

config = botocore.client.Config(signature_version=botocore.UNSIGNED)
object_url = boto3.client('s3', config=config).generate_presigned_url('get_object', ExpiresIn=0, Params={'Bucket': s3_bucket_name, 'Key': key_name})
print(object_url)