web-dev-qa-db-fra.com

Comment télécharger le dernier fichier d'un bucket S3 en utilisant Boto3?

Les autres questions que j'ai pu trouver faisaient référence à une ancienne version de Boto. Je souhaite télécharger le dernier fichier d'un bucket S3. Dans le documentation j'ai trouvé qu'il y a une méthode list_object_versions () qui vous obtient un IsLatest booléen. Malheureusement, je n'ai réussi qu'à établir une connexion et à télécharger un fichier. Pourriez-vous s'il vous plaît me montrer comment je peux étendre mon code pour obtenir le dernier fichier du compartiment? Je vous remercie

import boto3
conn = boto3.client('s3',
                    region_name="eu-west-1",
                    endpoint_url="customendpoint",
                    config=Config(signature_version="s3", s3={'addressing_style': 'path'}))

De là, je ne sais pas comment obtenir le dernier fichier ajouté à partir d'un compartiment appelé mytestbucket. Il y a plusieurs fichiers csv dans le bucket mais tous bien sûr avec un nom différent.

Mettre à jour:

import boto3
from botocore.client import Config

s3 = boto3.resource('s3', region_name="eu-west-1", endpoint_url="custom endpoint", aws_access_key_id = '1234', aws_secret_access_key = '1234', config=Config(signature_version="s3", s3={'addressing_style': 'path'}))
my_bucket = s3.Bucket('mytestbucket22')
unsorted = []
for file in my_bucket.objects.filter():
   unsorted.append(file)

files = [obj.key for obj in sorted(unsorted, key=get_last_modified, reverse=True)][0:9]

Cela me donne l'erreur suivante:

NameError: name 'get_last_modified' is not defined
6
jz22

Variation de la réponse que j'ai fournie: Boto3 S3, trier le seau par dernière modification . Vous pouvez modifier le code en fonction de vos besoins.

get_last_modified = lambda obj: int(obj['LastModified'].strftime('%s'))

s3 = boto3.client('s3')
objs = s3.list_objects_v2(Bucket='my_bucket')['Contents']
last_added = [obj['Key'] for obj in sorted(objs, key=get_last_modified)][0]

Si vous souhaitez inverser le tri:

[obj['Key'] for obj in sorted(objs, key=get_last_modified, reverse=True)][0]
10
helloV

Tu peux faire

import boto3

s3_client = boto3.client('s3')
response = s3_client.list_objects_v2(Bucket='bucket_name', Prefix='prefix')
all = response['Contents']        
latest = max(all, key=lambda x: x['LastModified'])
7
smaraf

C'est fondamentalement la même réponse que helloV dans le cas où vous utilisez Session comme je le fais.

from boto3.session import Session
import settings

session = Session(aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
                          aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)
s3 = session.resource("s3")

get_last_modified = lambda obj: int(obj.last_modified.strftime('%s'))


bckt = s3.Bucket("my_bucket")
objs = [obj for obj in bckt.objects.all()]

objs = [obj for obj in sorted(objs, key=get_last_modified)]
last_added = objs[-1].key

Le tri de objs vous permet de supprimer rapidement tous les fichiers sauf le dernier avec

for obj in objs[:-1]:
    s3.Object("my_bucket", obj.key).delete()
2
rpanai

Si vous avez beaucoup de fichiers, vous devrez utiliser la pagination comme mentionné par helloV. Voilà comment je l'ai fait.

get_last_modified = lambda obj: int(obj['LastModified'].strftime('%s'))
s3 = boto3.client('s3')
paginator = s3.get_paginator( "list_objects" )
page_iterator = paginator.paginate( Bucket = "BucketName", Prefix = "Prefix")
for page in page_iterator:
    if "Contents" in page:
        last_added = [obj['Key'] for obj in sorted( page["Contents"], key=get_last_modified)][-1]
1
SaadK

Vous devriez pouvoir télécharger la dernière version du fichier en utilisant la commande de téléchargement par défaut du fichier

import boto3
import botocore

BUCKET_NAME = 'mytestbucket'
KEY = 'fileinbucket.txt'

s3 = boto3.resource('s3')

try:
    s3.Bucket(BUCKET_NAME).download_file(KEY, 'downloadname.txt')
except botocore.exceptions.ClientError as e:
    if e.response['Error']['Code'] == "404":
        print("The object does not exist.")
    else:
        raise

Référence lien

Pour obtenir le dernier fichier modifié ou téléchargé, vous pouvez utiliser ce qui suit

s3 = boto3.resource('s3')
my_bucket = s3.Bucket('myBucket')
unsorted = []
for file in my_bucket.objects.filter():
   unsorted.append(file)

files = [obj.key for obj in sorted(unsorted, key=get_last_modified, 
    reverse=True)][0:9]

Comme réponse dans cette référence link déclare, ce n'est pas optimal mais cela fonctionne.

0
Ashan

Je voulais également télécharger le dernier fichier du compartiment s3 mais situé dans un dossier spécifique. Utilisez la fonction suivante pour obtenir le dernier nom de fichier en utilisant le nom et le préfixe du compartiment (qui est le nom du dossier).

import boto3

def get_latest_file_name(bucket_name,prefix):
    """
    Return the latest file name in an S3 bucket folder.

    :param bucket: Name of the S3 bucket.
    :param prefix: Only fetch keys that start with this prefix (folder  name).
    """
    s3_client = boto3.client('s3')
    objs = s3_client.list_objects_v2(Bucket=bucket_name)['Contents']
    shortlisted_files = dict()            
    for obj in objs:
        key = obj['Key']
        timestamp = obj['LastModified']
        # if key starts with folder name retrieve that key
        if key.startswith(prefix):              
            # Adding a new key value pair
            shortlisted_files.update( {key : timestamp} )   
    latest_filename = max(shortlisted_files, key=shortlisted_files.get)
    return latest_filename

latest_filename = get_latest_file_name(bucket_name='use_your_bucket_name',prefix = 'folder_name/')
0
Sayali Sonawane