Cómo cargar un archivo al directorio en el bucket de S3 usando boto

107

Quiero copiar un archivo en el depósito s3 usando python.

Ej: tengo nombre de cubo = prueba. Y en el cubo, tengo 2 carpetas con el nombre "volcado" y "entrada". Ahora quiero copiar un archivo del directorio local a la carpeta de "volcado" de S3 usando Python ... ¿Alguien puede ayudarme?

Dheeraj Gundra
fuente

Respuestas:

105

Prueba esto...

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)

[ACTUALIZACIÓN] No soy un pitonista, así que gracias por los avisos sobre las declaraciones de importación. Además, no recomendaría colocar credenciales dentro de su propio código fuente. Si está ejecutando esto dentro de AWS, use credenciales de IAM con perfiles de instancia ( http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html ) y para mantener el mismo comportamiento en su entorno de desarrollo / prueba, utilice algo como Hologram de AdRoll ( https://github.com/AdRoll/hologram )

Felipe García
fuente
8
Evitaría las múltiples líneas de importación, no pythonic. Mueva las líneas de importación a la parte superior, y para el boto, puede usar desde boto.s3.connection import S3Connection; conn = S3Connection (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY); cubo = conn.create_bucket (nombre del cubo ...); bucket.new_key (keyname, ...). set_contents_from_filename ....
cgseller
2
boto.s3.key.Key no existe el 1.7.12
Alex Pavy
actualización a partir de abril de 2020 siga este enlace upload_file_to_s3_using_python
Prayag Sharma
48

No hay necesidad de hacerlo tan complicado:

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)
vcarel
fuente
Esto funcionará, pero para archivos .zip grandes es posible que deba usar fragmentado. elastician.com/2010/12/s3-multipart-upload-in-boto.html
cgseller
2
Sí ... práctica menos complicada y de uso común
Leo Prince
1
Intenté esto, no funciona, pero k.set_contents_from_filename (testfile, cb = percent_cb, num_cb = 10) sí lo hace
Simon
1
¿Estás en el boto 2, más reciente? De todos modos, set_contents_from_filename es una opción aún más simple. Ve a por ello !
vcarel
3
key.set_contents_from_filename('some_file.zip')también funcionaría aquí. Ver doc . El código correspondiente para boto3 se puede encontrar aquí .
Greg Sadetsky
44
import boto3

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

s3.Bucket(BUCKET).upload_file("your/local/file", "dump/file")
Boris
fuente
¿Puede explicar esta línea? s3.Bucket (BUCKET) .upload_file ("su / local / archivo", "volcado / archivo")
venkat
@venkat "your / local / file" es una ruta de archivo como "/home/file.txt" en la computadora que usa python / boto y "dump / file" es un nombre clave para almacenar el archivo en el S3 Bucket. Ver: boto3.readthedocs.io/en/latest/reference/services/…
Josh S.
1
Parece que el usuario tiene claves de AWS preconfiguradas, para hacer esto, abra el símbolo del sistema de anaconda y escriba aws configure, ingrese su información y se conectará automáticamente con boto3. Consulte boto3.readthedocs.io/en/latest/guide/quickstart.html
seeiespi
En mi opinión, la solución más simple, tan fácil como tinys3 pero sin la necesidad de otra dependencia externa. También recomiendo encarecidamente configurar sus claves de AWS con aws configureanticipación para facilitar su vida.
barlaensdoonn
¿Qué sucede cuando hay varios perfiles en las credenciales? cómo pasar las credenciales específicas
Tara Prasad Gurung
36

Usé esto y es muy simple de implementar.

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/

Oren Efron
fuente
No creo que esto funcione para archivos grandes. Tuve que usar esto: docs.pythonboto.org/en/latest/s3_tut.html#storing-large-data
wordsforthewise
Eso también me llevó a esta solución: github.com/boto/boto/issues/2207#issuecomment-60682869 y esto: stackoverflow.com/questions/5396932/…
wordsforthewise
6
Dado que el proyecto tinys3 está abandonado, no debería utilizarlo. github.com/smore-inc/tinys3/issues/45
Halil Kaskavalci
Esto de plano ya no funcionó para mí en 2019. tinys3 no solo está abandonado ... No creo que ya funcione. Para cualquier otra persona que decida probar esto, no se sorprenda si obtiene errores 403. Sin boto3.clientembargo, una solución simple (como la respuesta de Manish Mehra) funcionó de inmediato.
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)
Manish Mehra
fuente
¿Qué es filepath y qué es folder_name + filename? es confuso
colintobing
@colintobing filepath es la ruta del archivo en el clúster y folder_name / filename es la convención de nomenclatura que le gustaría tener dentro del depósito s3
Manish Mehra
2
@ManishMehra La respuesta sería mejor si la editara para aclarar el punto de confusión de colintobing; no es obvio sin verificar los documentos qué parámetros se refieren a las rutas locales y cuáles a las rutas de S3 sin verificar los documentos o leer los comentarios. (Una vez hecho esto, puede marcar para que se eliminen todos los comentarios aquí, ya que serán obsoletos).
Mark Amery
aws_access_key_idy aws_secret_access_keytambién puede configurarse con la AWS CLI y almacenarse fuera del script para que se pueda llamar a `client = boto3.client ('s3')
yvesva
16

Sube el archivo a s3 dentro de una sesión con credenciales.

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')
Roman Orac
fuente
¿Qué es s3_output_key?
Roelant
Es el nombre de archivo en el depósito de S3.
Roman Orac
12

Esto también funcionará:

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"   
Piyush S. Wanare
fuente
7

Este es un trazador de líneas de tres. Simplemente siga las instrucciones de la documentación de 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')

Algunos argumentos importantes son:

Parámetros:

  • Nombre de archivo ( str): la ruta al archivo para cargar.
  • Bucket ( str): el nombre del bucket al que se cargará.
  • Clave ( str): el nombre del que desea asignar a su archivo en su depósito s3. Este podría ser el mismo que el nombre del archivo o un nombre diferente de su elección, pero el tipo de archivo debe seguir siendo el mismo.

    Nota: Supongo que ha guardado sus credenciales en una ~\.awscarpeta como se sugiere en las mejores prácticas de configuración en la documentación de boto3 .

  • Samuel Nde
    fuente
    Gracias Nde Samuel, eso funcionó conmigo ... Una cosa que se requirió adicionalmente en mi caso fue tener el depósito ya creado, para evitar un error de "" El depósito especificado no existe "".
    HassanSh__3571619
    @ HassanSh__3571619 Me alegro de que haya ayudado.
    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)
    Shakti
    fuente
    4

    Usando 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

    Para más: - https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html

    Noufal Valapra
    fuente
    1

    Para cargar un ejemplo de carpeta como el siguiente código y la imagen de la carpeta S3 ingrese la descripción de la imagen aquí

    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)

    PD: para obtener más URL de referencia

    Willie Cheng
    fuente
    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')
    Martín
    fuente
    ¡Una explicación de texto con lo que hace su código será agradable!
    Nick
    0

    Tengo algo que me parece que tiene un poco más de orden:

    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
    
    

    Hay tres variables importantes en este caso, el CUBO const, el file_to_upload y el nombre_archivo

    BUCKET: es el nombre de su bucket de S3

    file_to_upload_path: debe ser la ruta del archivo que desea cargar

    file_name: es el archivo resultante y la ruta en su depósito (aquí es donde agrega carpetas o lo que sea)

    Hay muchas formas, pero puede reutilizar este código en otro script como este

    import S3
    
    def some_function():
        S3.S3().upload_file(path_to_file, final_file_name)
    Jesús caminante
    fuente