Come caricare un file nella directory nel bucket S3 utilizzando boto


107

Voglio copiare un file nel bucket s3 usando python.

Es: ho nome bucket = test. E nel secchio, ho 2 cartelle denominate "dump" e "input". Ora voglio copiare un file dalla directory locale alla cartella "dump" di S3 usando python ... Qualcuno può aiutarmi?

Risposte:


105

Prova questo...

import boto
import boto.s3
import sys
from boto.s3.key import Key

AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''

bucket_name = AWS_ACCESS_KEY_ID.lower() + '-dump'
conn = boto.connect_s3(AWS_ACCESS_KEY_ID,
        AWS_SECRET_ACCESS_KEY)


bucket = conn.create_bucket(bucket_name,
    location=boto.s3.connection.Location.DEFAULT)

testfile = "replace this with an actual filename"
print 'Uploading %s to Amazon S3 bucket %s' % \
   (testfile, bucket_name)

def percent_cb(complete, total):
    sys.stdout.write('.')
    sys.stdout.flush()


k = Key(bucket)
k.key = 'my test file'
k.set_contents_from_filename(testfile,
    cb=percent_cb, num_cb=10)

[AGGIORNAMENTO] Non sono un pythonist, quindi grazie per l'avvertenza sulle istruzioni di importazione. Inoltre, non consiglierei di inserire le credenziali nel tuo codice sorgente. Se lo stai eseguendo all'interno di AWS, utilizza le credenziali IAM con i profili di istanza ( http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html ) e per mantenere lo stesso comportamento in il tuo ambiente Dev / Test, usa qualcosa come Hologram di AdRoll ( https://github.com/AdRoll/hologram )


8
Eviterei le linee di importazione multiple, non pitoniche. Sposta le linee di importazione in alto e per il boto puoi usare from boto.s3.connection import S3Connection; conn = S3Connection (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY); bucket = conn.create_bucket (bucketname ...); bucket.new_key (keyname, ...). set_contents_from_filename ....
cgseller

2
boto.s3.key.Key non esiste il 1.7.12
Alex Pavy

aggiornamento da aprile 2020 segui questo link upload_file_to_s3_using_python
Prayag Sharma

48

Non c'è bisogno di renderlo così complicato:

s3_connection = boto.connect_s3()
bucket = s3_connection.get_bucket('your bucket name')
key = boto.s3.key.Key(bucket, 'some_file.zip')
with open('some_file.zip') as f:
    key.send_file(f)

Funzionerà, ma per file .zip di grandi dimensioni potrebbe essere necessario utilizzare chunked. elastician.com/2010/12/s3-multipart-upload-in-boto.html
cgseller

2
Sì .. pratica meno complicata e comunemente usata
Leo Prince

1
Ho provato questo, non funziona, ma k.set_contents_from_filename (testfile, cb = percent_cb, num_cb = 10) funziona
Simon

1
Sei su Boto 2, ultimo? Ad ogni modo, set_contents_from_filename è un'opzione ancora più semplice. Fallo !
vcarel

3
key.set_contents_from_filename('some_file.zip')funzionerebbe anche qui. Vedi doc . Il codice corrispondente per boto3 può essere trovato qui .
Greg Sadetsky

44
import boto3

s3 = boto3.resource('s3')
BUCKET = "test"

s3.Bucket(BUCKET).upload_file("your/local/file", "dump/file")

puoi spiegare questa riga s3.Bucket (BUCKET) .upload_file ("your / local / file", "dump / file")
venkat

@venkat "your / local / file" è un percorso file come "/home/file.txt" sul computer che utilizza python / boto e "dump / file" è un nome chiave per memorizzare il file in S3 Bucket. Vedi: boto3.readthedocs.io/en/latest/reference/services/…
Josh S.

1
Sembra che l'utente abbia chiavi AWS preconfigurate, per fare ciò apri il prompt dei comandi di anaconda e digita aws configure, inserisci le tue informazioni e ti connetti automaticamente con boto3. Controlla boto3.readthedocs.io/en/latest/guide/quickstart.html
seeiespi

soluzione più semplice IMO, altrettanto facile come tinys3 ma senza la necessità di un'altra dipendenza esterna. Consiglia inoltre vivamente di configurare le chiavi AWS in aws configureanticipo per semplificarti la vita.
barlaensdoonn

Cosa succede quando sono presenti più profili nelle credenziali. come passare le credenziali specifiche
Tara Prasad Gurung

36

L'ho usato ed è molto semplice da implementare

import tinys3

conn = tinys3.Connection('S3_ACCESS_KEY','S3_SECRET_KEY',tls=True)

f = open('some_file.zip','rb')
conn.upload('some_file.zip',f,'my_bucket')

https://www.smore.com/labs/tinys3/


Non penso che funzioni per file di grandi dimensioni. Ho dovuto usare questo: docs.pythonboto.org/en/latest/s3_tut.html#storing-large-data
wordsforthewise


6
Poiché il progetto tinys3 è abbandonato, non dovresti usarlo. github.com/smore-inc/tinys3/issues/45
Halil Kaskavalci

Questo flat out non ha funzionato più per me nel 2019. tinys3 non è solo abbandonato ... non penso che funzioni più. Per chiunque altro decida di provare questo, non sorprenderti se ricevi errori 403. Una boto3.clientsoluzione semplice (come la risposta di Manish Mehra) ha funzionato immediatamente, però.
Russ

16
from boto3.s3.transfer import S3Transfer
import boto3
#have all the variables populated which are required below
client = boto3.client('s3', aws_access_key_id=access_key,aws_secret_access_key=secret_key)
transfer = S3Transfer(client)
transfer.upload_file(filepath, bucket_name, folder_name+"/"+filename)

cos'è filepath e cos'è nome_cartella + nomefile? è
fonte

@colintobing filepath è il percorso del file sul cluster e folder_name / filename è la convenzione di denominazione che vorresti avere all'interno del bucket s3
Manish Mehra

2
@ManishMehra La risposta sarebbe migliore se la modificassi per chiarire il punto di confusione di colintobing; non è ovvio senza controllare i documenti quali parametri si riferiscono a percorsi locali e quali a percorsi S3 senza controllare i documenti o leggere i commenti. (Una volta fatto, puoi contrassegnare per eliminare tutti i commenti qui, poiché saranno obsoleti.)
Mark Amery,

aws_access_key_ide aws_secret_access_keypuò anche essere configurato con AWS CLI e archiviato fuori dallo script in modo che `client = boto3.client ('s3') possa essere chiamato
yvesva

16

Carica il file su s3 all'interno di una sessione con le credenziali.

import boto3

session = boto3.Session(
    aws_access_key_id='AWS_ACCESS_KEY_ID',
    aws_secret_access_key='AWS_SECRET_ACCESS_KEY',
)
s3 = session.resource('s3')
# Filename - File to upload
# Bucket - Bucket to upload to (the top level directory under AWS S3)
# Key - S3 object name (can contain subdirectories). If not specified then file_name is used
s3.meta.client.upload_file(Filename='input_file_path', Bucket='bucket_name', Key='s3_output_key')

Cos'è la s3_output_key?
Roelant

È il nome del file nel bucket S3.
Roman Orac

12

Funzionerà anche:

import os 
import boto
import boto.s3.connection
from boto.s3.key import Key

try:

    conn = boto.s3.connect_to_region('us-east-1',
    aws_access_key_id = 'AWS-Access-Key',
    aws_secret_access_key = 'AWS-Secrete-Key',
    # host = 's3-website-us-east-1.amazonaws.com',
    # is_secure=True,               # uncomment if you are not using ssl
    calling_format = boto.s3.connection.OrdinaryCallingFormat(),
    )

    bucket = conn.get_bucket('YourBucketName')
    key_name = 'FileToUpload'
    path = 'images/holiday' #Directory Under which file should get upload
    full_key_name = os.path.join(path, key_name)
    k = bucket.new_key(full_key_name)
    k.set_contents_from_filename(key_name)

except Exception,e:
    print str(e)
    print "error"   

7

Questo è un tre linee. Basta seguire le istruzioni sulla documentazione di boto3 .

import boto3
s3 = boto3.resource(service_name = 's3')
s3.meta.client.upload_file(Filename = 'C:/foo/bar/baz.filetype', Bucket = 'yourbucketname', Key = 'baz.filetype')

Alcuni argomenti importanti sono:

Parametri:

  • Filename ( str) - Il percorso del file da caricare.
  • Bucket ( str): il nome del bucket in cui caricare.
  • Key ( str): il nome dell'oggetto che desideri assegnare al file nel bucket s3. Potrebbe essere lo stesso del nome del file o un nome diverso a tua scelta, ma il tipo di file dovrebbe rimanere lo stesso.

    Nota: presumo che tu abbia salvato le tue credenziali in una ~\.awscartella come suggerito nelle migliori pratiche di configurazione nella documentazione di boto3 .


  • Grazie Nde Samuel, che ha funzionato con me ... Una cosa che era richiesta in più nel mio caso era che il bucket fosse già stato creato, per evitare un errore di "" Il bucket specificato non esiste "".
    HassanSh__3571619

    @ HassanSh__3571619 Sono contento che abbia aiutato.
    Samuel Nde

    5
    import boto
    from boto.s3.key import Key
    
    AWS_ACCESS_KEY_ID = ''
    AWS_SECRET_ACCESS_KEY = ''
    END_POINT = ''                          # eg. us-east-1
    S3_HOST = ''                            # eg. s3.us-east-1.amazonaws.com
    BUCKET_NAME = 'test'        
    FILENAME = 'upload.txt'                
    UPLOADED_FILENAME = 'dumps/upload.txt'
    # include folders in file path. If it doesn't exist, it will be created
    
    s3 = boto.s3.connect_to_region(END_POINT,
                               aws_access_key_id=AWS_ACCESS_KEY_ID,
                               aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
                               host=S3_HOST)
    
    bucket = s3.get_bucket(BUCKET_NAME)
    k = Key(bucket)
    k.key = UPLOADED_FILENAME
    k.set_contents_from_filename(FILENAME)

    4

    Utilizzando boto3

    import logging
    import boto3
    from botocore.exceptions import ClientError
    
    
    def upload_file(file_name, bucket, object_name=None):
        """Upload a file to an S3 bucket
    
        :param file_name: File to upload
        :param bucket: Bucket to upload to
        :param object_name: S3 object name. If not specified then file_name is used
        :return: True if file was uploaded, else False
        """
    
        # If S3 object_name was not specified, use file_name
        if object_name is None:
            object_name = file_name
    
        # Upload the file
        s3_client = boto3.client('s3')
        try:
            response = s3_client.upload_file(file_name, bucket, object_name)
        except ClientError as e:
            logging.error(e)
            return False
        return True

    Per ulteriori informazioni: - https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html


    1

    Per esempio di cartella di caricamento come codice seguente e immagine della cartella S3 inserisci qui la descrizione dell'immagine

    import boto
    import boto.s3
    import boto.s3.connection
    import os.path
    import sys    
    
    # Fill in info on data to upload
    # destination bucket name
    bucket_name = 'willie20181121'
    # source directory
    sourceDir = '/home/willie/Desktop/x/'  #Linux Path
    # destination directory name (on s3)
    destDir = '/test1/'   #S3 Path
    
    #max size in bytes before uploading in parts. between 1 and 5 GB recommended
    MAX_SIZE = 20 * 1000 * 1000
    #size of parts when uploading in parts
    PART_SIZE = 6 * 1000 * 1000
    
    access_key = 'MPBVAQ*******IT****'
    secret_key = '11t63yDV***********HgUcgMOSN*****'
    
    conn = boto.connect_s3(
            aws_access_key_id = access_key,
            aws_secret_access_key = secret_key,
            host = '******.org.tw',
            is_secure=False,               # uncomment if you are not using ssl
            calling_format = boto.s3.connection.OrdinaryCallingFormat(),
            )
    bucket = conn.create_bucket(bucket_name,
            location=boto.s3.connection.Location.DEFAULT)
    
    
    uploadFileNames = []
    for (sourceDir, dirname, filename) in os.walk(sourceDir):
        uploadFileNames.extend(filename)
        break
    
    def percent_cb(complete, total):
        sys.stdout.write('.')
        sys.stdout.flush()
    
    for filename in uploadFileNames:
        sourcepath = os.path.join(sourceDir + filename)
        destpath = os.path.join(destDir, filename)
        print ('Uploading %s to Amazon S3 bucket %s' % \
               (sourcepath, bucket_name))
    
        filesize = os.path.getsize(sourcepath)
        if filesize > MAX_SIZE:
            print ("multipart upload")
            mp = bucket.initiate_multipart_upload(destpath)
            fp = open(sourcepath,'rb')
            fp_num = 0
            while (fp.tell() < filesize):
                fp_num += 1
                print ("uploading part %i" %fp_num)
                mp.upload_part_from_file(fp, fp_num, cb=percent_cb, num_cb=10, size=PART_SIZE)
    
            mp.complete_upload()
    
        else:
            print ("singlepart upload")
            k = boto.s3.key.Key(bucket)
            k.key = destpath
            k.set_contents_from_filename(sourcepath,
                    cb=percent_cb, num_cb=10)

    PS: per più URL di riferimento


    0
    xmlstr = etree.tostring(listings,  encoding='utf8', method='xml')
    conn = boto.connect_s3(
            aws_access_key_id = access_key,
            aws_secret_access_key = secret_key,
            # host = '<bucketName>.s3.amazonaws.com',
            host = 'bycket.s3.amazonaws.com',
            #is_secure=False,               # uncomment if you are not using ssl
            calling_format = boto.s3.connection.OrdinaryCallingFormat(),
            )
    conn.auth_region_name = 'us-west-1'
    
    bucket = conn.get_bucket('resources', validate=False)
    key= bucket.get_key('filename.txt')
    key.set_contents_from_string("SAMPLE TEXT")
    key.set_canned_acl('public-read')

    Una spiegazione testuale con ciò che fa il tuo codice sarà carina!
    Nick il

    0

    Ho qualcosa che mi sembra abbia un po 'più di ordine:

    import boto3
    from pprint import pprint
    from botocore.exceptions import NoCredentialsError
    
    
    class S3(object):
        BUCKET = "test"
        connection = None
    
        def __init__(self):
            try:
                vars = get_s3_credentials("aws")
                self.connection = boto3.resource('s3', 'aws_access_key_id',
                                                 'aws_secret_access_key')
            except(Exception) as error:
                print(error)
                self.connection = None
    
    
        def upload_file(self, file_to_upload_path, file_name):
            if file_to_upload is None or file_name is None: return False
            try:
                pprint(file_to_upload)
                file_name = "your-folder-inside-s3/{0}".format(file_name)
                self.connection.Bucket(self.BUCKET).upload_file(file_to_upload_path, 
                                                                          file_name)
                print("Upload Successful")
                return True
    
            except FileNotFoundError:
                print("The file was not found")
                return False
    
            except NoCredentialsError:
                print("Credentials not available")
                return False
    
    

    Ci sono tre variabili importanti qui, la const BUCKET , il file_to_upload e il file_name

    BUCKET: è il nome del tuo bucket S3

    file_to_upload_path: deve essere il percorso del file che desideri caricare

    file_name: è il file e il percorso risultante nel tuo bucket (qui è dove aggiungi cartelle o altro)

    Ci sono molti modi ma puoi riutilizzare questo codice in un altro script come questo

    import S3
    
    def some_function():
        S3.S3().upload_file(path_to_file, final_file_name)
    Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
    Licensed under cc by-sa 3.0 with attribution required.