Como fazer upload de um arquivo para o diretório no intervalo S3 usando boto


107

Eu quero copiar um arquivo no balde s3 usando python.

Ex: tenho nome do intervalo = teste. E no balde, tenho 2 pastas de nomes "despejo" e "entrada". Agora eu quero copiar um arquivo do diretório local para a pasta S3 "dump" usando python ... Alguém pode me ajudar?

Respostas:


105

Experimente isso ...

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)

[ATUALIZAÇÃO] Eu não sou um pythonista, então obrigado pelo aviso sobre as instruções de importação. Além disso, não recomendo colocar credenciais dentro de seu próprio código-fonte. Se você estiver executando isso dentro da AWS, use as credenciais IAM com perfis de instância ( http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html ) e para manter o mesmo comportamento em seu ambiente de Dev / Test, use algo como Hologram de AdRoll ( https://github.com/AdRoll/hologram )


8
Eu evitaria as múltiplas linhas de importação, não pythônicas. Mova as linhas de importação para o topo, e para o boto, você pode usar from boto.s3.connection import S3Connection; conexão = 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 não existe em 1.7.12
Alex Pavy

atualização a partir de abril de 2020 siga este link upload_file_to_s3_using_python
Prayag Sharma

48

Não há necessidade de tornar isso tão 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)

Isso funcionará, mas para arquivos .zip grandes, você pode precisar usar blocos. elastician.com/2010/12/s3-multipart-upload-in-boto.html
cgseller

2
Sim .. prática menos complicada e comumente usada
Leo Prince

1
Eu tentei isso, não funciona, mas k.set_contents_from_filename (testfile, cb = percent_cb, num_cb = 10) funciona
Simon

1
Você está no boto 2, mais recente? De qualquer forma, set_contents_from_filename é uma opção ainda mais simples. Vá em frente !
vcarel

3
key.set_contents_from_filename('some_file.zip')também funcionaria aqui. Veja doc . O código correspondente para boto3 pode ser encontrado aqui .
Greg Sadetsky

44
import boto3

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

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

você pode explicar esta linha s3.Bucket (BUCKET) .upload_file ("seu / local / arquivo", "despejar / arquivo")
venkat

@venkat "seu / local / arquivo" é um caminho de arquivo como "/home/file.txt" no computador usando python / boto e "dump / arquivo" é um nome-chave para armazenar o arquivo no S3 Bucket. Consulte: boto3.readthedocs.io/en/latest/reference/services/…
Josh S.

1
Parece que o usuário tem chaves AWS pré-configuradas, para fazer isso, abra o prompt de comando do anaconda e digite aws configure, insira suas informações e você se conectará automaticamente ao boto3. Verifique boto3.readthedocs.io/en/latest/guide/quickstart.html
seeiespi

solução mais simples IMO, tão fácil quanto tinys3, mas sem a necessidade de outra dependência externa. Também é altamente recomendável configurar suas chaves AWS com aws configureantecedência para tornar sua vida mais fácil.
barlaensdoonn

O que acontece quando há vários perfis nas credenciais. como passar as credenciais específicas
Tara Prasad Gurung

36

Eu usei isso e é muito simples 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/


Não acho que isso funcione para arquivos grandes. Tive de usar isto: docs.pythonboto.org/en/latest/s3_tut.html#storing-large-data
wordsforthewise


6
Como o projeto tinys3 foi abandonado, você não deve usá-lo. github.com/smore-inc/tinys3/issues/45
Halil Kaskavalci

Isso não funcionou mais para mim em 2019. tinys3 não é apenas abandonado ... Acho que não funciona mais. Para qualquer pessoa que decidir tentar isso, não se surpreenda se obtiver erros 403. Uma boto3.clientsolução simples (como a resposta de Manish Mehra) funcionou imediatamente, no entanto.
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)

o que é caminho de arquivo e o que é nome_da_pasta + nome do arquivo? é confuso
colinto em

@colintobing filepath é o caminho do arquivo no cluster e folder_name / filename é a convenção de nomenclatura que você gostaria de ter dentro do intervalo s3
Manish Mehra

2
@ManishMehra A resposta seria melhor se você editasse para esclarecer o ponto de confusão de colintobing; não é óbvio sem verificar os documentos quais parâmetros se referem aos caminhos locais e quais aos caminhos do S3 sem verificar os documentos ou ler os comentários. (Uma vez feito isso, você pode sinalizar para que todos os comentários aqui sejam eliminados, pois eles estarão obsoletos.)
Mark Amery

aws_access_key_ide aws_secret_access_keytambém pode ser configurado com o AWS CLI e armazenado fora do script para que `client = boto3.client ('s3') possa ser chamado
yvesva

16

Faça upload do arquivo para s3 em uma sessão com credenciais.

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')

O que é s3_output_key?
Roelant

É o nome do arquivo no depósito S3.
Roman Orac

12

Isso também 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"   

7

Este é um três linhas. Basta seguir as instruções na documentação do 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')

Alguns argumentos importantes são:

Parâmetros:

  • Nome do arquivo ( str) - O caminho para o arquivo a ser carregado.
  • Bucket ( str) - o nome do bucket para fazer upload.
  • Key ( str) - O nome do que você deseja atribuir ao seu arquivo em seu intervalo s3. Pode ser igual ao nome do arquivo ou um nome diferente de sua escolha, mas o tipo de arquivo deve permanecer o mesmo.

    Observação: presumo que você salvou suas credenciais em uma ~\.awspasta, conforme sugerido nas melhores práticas de configuração na documentação do boto3 .


  • Obrigado Nde Samuel, que trabalhou comigo ... Uma coisa que foi adicional necessária no meu caso foi que o bucket já tivesse sido criado, para evitar um erro de "" O bucket especificado não existe "".
    HassanSh__3571619

    @ HassanSh__3571619 Estou feliz por ter ajudado.
    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

    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 mais informações: - https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html


    1

    Por exemplo de pasta de upload como seguinte código e imagem da pasta S3 insira a descrição da imagem aqui

    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: Para mais URL de referência


    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')

    Uma explicação em texto com o que o seu código faz será legal!
    Nick

    0

    Tenho algo que me parece um pouco mais organizado:

    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
    
    

    Existem três variáveis ​​importantes aqui, o BUCKET const, o file_to_upload e o file_name

    BUCKET: é o nome do seu intervalo S3

    file_to_upload_path: deve ser o caminho do arquivo que você deseja enviar

    file_name: é o arquivo resultante e o caminho em seu intervalo (é onde você adiciona pastas ou o que quer que seja)

    Existem muitas maneiras, mas você pode reutilizar este código em outro script como este

    import S3
    
    def some_function():
        S3.S3().upload_file(path_to_file, final_file_name)
    Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
    Licensed under cc by-sa 3.0 with attribution required.