Jak przesłać plik do katalogu w zasobniku S3 przy użyciu boto

107

Chcę skopiować plik w wiadrze s3 za pomocą Pythona.

Np. Mam wiadro name = test. A w wiadrze mam 2 foldery o nazwach „dump” i „input”. Teraz chcę skopiować plik z katalogu lokalnego do folderu „dump” S3 za pomocą Pythona ... Czy ktoś może mi pomóc?

Dheeraj Gundra
źródło

Odpowiedzi:

105

Spróbuj tego...

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)

[UPDATE] Nie jestem pythonistą, więc dziękuję za ostrzeżenia o instrukcjach importu. Nie polecałbym również umieszczania poświadczeń we własnym kodzie źródłowym. Jeśli uruchamiasz to w AWS, użyj IAM Credentials with Instance Profiles ( http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html ) i zachowaj to samo zachowanie w swoje środowisko Dev / Test, użyj czegoś takiego jak Hologram z AdRoll ( https://github.com/AdRoll/hologram )

Felipe Garcia
źródło
8
Unikałbym wielu linii importu, a nie Pythona. Przenieś linie importu na górę, a dla boto możesz użyć from boto.s3.connection import S3Connection; conn = S3Connection (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY); bucket = conn.create_bucket (nazwa zasobnika ...); bucket.new_key (nazwa klucza, ...). set_contents_from_filename ....
cgseller
2
boto.s3.key.Key nie istnieje w dniu 1.7.12
Alex Pavy
aktualizacja od kwietnia 2020 r., kliknij ten link upload_file_to_s3_using_python
Prayag Sharma
48

Nie ma potrzeby, aby było to aż tak skomplikowane:

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
źródło
To zadziała, ale w przypadku dużych plików .zip może być konieczne użycie fragmentów. elastician.com/2010/12/s3-multipart-upload-in-boto.html
cgseller
2
Tak… mniej skomplikowana i powszechnie stosowana praktyka
Leo Prince
1
Próbowałem tego, to nie działa, ale k.set_contents_from_filename (testfile, cb = percent_cb, num_cb = 10) działa
Simon
1
Czy korzystasz z Boto 2, najnowszego? W każdym razie set_contents_from_filename jest jeszcze prostszą opcją. Idź po to !
vcarel
3
key.set_contents_from_filename('some_file.zip')działałby również tutaj. Zobacz dok . Odpowiedni kod dla boto3 można znaleźć tutaj .
Greg Sadetsky
44
import boto3

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

s3.Bucket(BUCKET).upload_file("your/local/file", "dump/file")
Boris
źródło
czy możesz wyjaśnić tę linię s3.Bucket (BUCKET) .upload_file ("twój / lokalny / plik", "dump / plik")
venkat
@venkat „twój / lokalny / plik” to ścieżka do pliku, taka jak „/home/file.txt” na komputerze przy użyciu python / boto, a „dump / file” to nazwa klucza do przechowywania pliku w zasobniku S3. Zobacz: boto3.readthedocs.io/en/latest/reference/services/…
Josh S.
1
Wygląda na to, że użytkownik ma wstępnie skonfigurowane klucze AWS, aby to zrobić, otwórz wiersz poleceń anaconda i wpisz aws configure, wprowadź swoje informacje, a automatycznie połączysz się z boto3. Sprawdź boto3.readthedocs.io/en/latest/guide/quickstart.html
seeiespi
najprostsze rozwiązanie IMO, równie łatwe jak tinys3, ale bez potrzeby stosowania innej zewnętrznej zależności. Zdecydowanie zalecamy również wcześniejsze skonfigurowanie kluczy AWS, aws configureaby ułatwić sobie życie.
barlaensdoonn
Co się dzieje, gdy w poświadczeniach jest wiele profili. jak przekazać konkretne uprawnienia
Tara Prasad Gurung
36

Użyłem tego i jest to bardzo proste do wdrożenia

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
źródło
Myślę, że to nie działa w przypadku dużych plików. Musiałem użyć tego: docs.pythonboto.org/en/latest/s3_tut.html#storing-large-data
wordsforthewise
To również doprowadziło mnie do tej poprawki: github.com/boto/boto/issues/2207#issuecomment-60682869 i to: stackoverflow.com/questions/5396932/…
wordsforthewise
6
Ponieważ projekt tinys3 został porzucony, nie powinieneś tego używać. github.com/smore-inc/tinys3/issues/45
Halil Kaskavalci
To płaskie rozwiązanie już dla mnie nie działało w 2019 roku. Tinys3 nie jest po prostu porzucony ... Myślę, że już nie działa. Dla każdego, kto zdecyduje się to wypróbować, nie zdziw się, jeśli otrzymasz błędy 403. Jednak proste boto3.clientrozwiązanie (jak odpowiedź Manisha Mehry) zadziałało natychmiast.
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
źródło
co to jest ścieżka pliku i co to jest nazwa_folderu + nazwa pliku? to jest mylące
colintobing
@colintobing ścieżka pliku to ścieżka do pliku w klastrze, a nazwa_folderu / nazwa pliku to konwencja nazewnictwa, którą chciałbyś mieć w zasobniku s3
Manish Mehra
2
@ManishMehra Odpowiedź byłaby lepsza, gdybyś ją zredagował, aby wyjaśnić niejasności Colintobinga; nie jest oczywiste bez sprawdzania dokumentów, które parametry odnoszą się do ścieżek lokalnych, a które do ścieżek S3, bez sprawdzania dokumentów lub czytania komentarzy. (Gdy to zrobisz, możesz oznaczyć, że wszystkie komentarze tutaj zostaną wyczyszczone, ponieważ będą przestarzałe.)
Mark Amery,
aws_access_key_idi aws_secret_access_keymoże być również skonfigurowany za pomocą interfejsu wiersza polecenia AWS i przechowywany poza skryptem, dzięki czemu można wywołać `client = boto3.client ('s3')
yvesva
16

Prześlij plik do s3 w ramach sesji z poświadczeniami.

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
źródło
Co to jest s3_output_key?
Roelant
Jest to nazwa pliku w zasobniku S3.
Roman Orac
12

To również zadziała:

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
źródło
7

To jest trzy linijka. Po prostu postępuj zgodnie z instrukcjami w dokumentacji 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')

Oto kilka ważnych argumentów:

Parametry:

  • Nazwastr pliku ( ) - ścieżka do pliku do przesłania.
  • Zasobnik ( str) - nazwa zasobnika do przesłania.
  • Klucz ( str) - nazwa, którą chcesz przypisać do swojego pliku w swoim segmencie s3. Może to być ta sama nazwa pliku lub inna wybrana nazwa, ale typ pliku powinien pozostać taki sam.

    Uwaga: Zakładam, że zapisałeś swoje poświadczenia w ~\.awsfolderze zgodnie z zaleceniami najlepszych praktyk konfiguracyjnych w dokumentacji boto3 .

  • Samuel Nde
    źródło
    Dziękuję Nde Samuel, że ze mną współpracował ... Dodatkową rzeczą, która była wymagana w moim przypadku, było to, że wiadro zostało już utworzone, aby uniknąć błędu "" Określony zasobnik nie istnieje "".
    HassanSh__3571619
    @ HassanSh__3571619 Cieszę się, że pomogło.
    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
    źródło
    4

    Korzystanie z 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

    Więcej: - https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html

    Noufal Valapra
    źródło
    1

    Przykład folderu do przesłania w następujący sposób: kod i obraz folderu S3 wprowadź opis obrazu tutaj

    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: Więcej informacji na temat adresu URL

    Willie Cheng
    źródło
    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')
    Jaskółka oknówka
    źródło
    Wyjaśnienie tekstowe z tym, co robi twój kod, będzie miłe!
    Nick
    0

    Mam coś, co wydaje mi się nieco bardziej uporządkowane:

    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
    
    

    Są tutaj trzy ważne zmienne , stała BUCKET , plik_do_wrzucenia i nazwa_pliku

    BUCKET: to nazwa twojego wiadra S3

    file_to_upload_path: musi być ścieżką do pliku, który chcesz przesłać

    file_name: to wynikowy plik i ścieżka w Twoim wiadrze (tutaj dodajesz foldery lub cokolwiek innego)

    Jest wiele sposobów, ale możesz ponownie użyć tego kodu w innym skrypcie, takim jak ten

    import S3
    
    def some_function():
        S3.S3().upload_file(path_to_file, final_file_name)
    Jesus Walker
    źródło