web-dev-qa-db-fra.com

Transférer sur Amazon S3 à l'aide de Boto3 et renvoyer l'URL publique

Je suis en train d'essayer de télécharger des fichiers sur s3 à l'aide de Boto3, de rendre public ce fichier téléchargé et de le renvoyer sous forme d'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 
    })

J'ai cherché dans toute la documentation mais je n'ai trouvé aucun lien décrivant comment faire. Quelqu'un peut-il expliquer ou fournir une ressource où je peux trouver l'âme?

16
Yaswanth Kumar

Je suis dans la même situation .. Impossible de trouver quoi que ce soit dans la documentation Boto3 au-delà de generate_presigned_url, ce qui n'est pas ce dont j'ai besoin dans mon cas car j'ai des objets S3 lisibles en public.

Le meilleur que j'ai trouvé est:

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)

Vous pouvez essayer de publier sur la liste des problèmes de boto3 github pour une meilleure solution.

27
Sam Keen

J'ai eu le même problème… .. En supposant que vous connaissiez le nom du compartiment dans lequel vous souhaitez stocker vos données, vous pouvez ensuite utiliser les éléments suivants:

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)
12
Eron Castro

La meilleure solution que j'ai trouvée est toujours d'utiliser le generate_presigned_url, mais le Client.Config.signature_version doit être défini sur botocore.UNSIGNED.

Ce qui suit renvoie le lien public sans les éléments de signature.

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

Les discussions pertinentes sur le référentiel boto3 sont:

3
wonton

Quelqu'un qui souhaite créer une URL directe pour un objet accessible au public afin d'éviter d'utiliser generate_presigned_url pour une raison quelconque,

Veuillez construire l'URL avec urllib.parse.quote_plus en tenant compte des espaces et des problèmes de caractères spéciaux.

  • Ma clé d'objet: 2018-11-26 16:34:48.351890+09:00.jpg veuillez noter les espaces et ':'  
  • Lien public S3 dans la console aws: https://s3.my_region.amazonaws.com/my_bucket_name/2018-11-26+16%3A34%3A48.351890%2B09%3A00.jpg

Le code ci-dessous était OK pour moi 

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)
0
Jay Lim