【问题标题】:Boto3 not uploading zip file to S3 pythonBoto3没有将zip文件上传到S3 python
【发布时间】:2018-03-29 09:30:09
【问题描述】:

我正在尝试使用 boto3 for python 将 .zip 文件上传到 S3,但我目录中的 .zip 文件未正确上传。 该代码下载给定用户的所有电子邮件,将它们压缩到同一目录中,然后将它们上传到 S3 存储桶。 问题是上传的文件不是我打算上传的文件。而是仅显示 18kb 的文件。

代码如下:

import sys
import imaplib
import getpass
import email
import shutil
import boto3
import os

username = input("Enter user's first name: ")
surname = input("Enter user's surname: ")
email_address = username + "." + surname + "@gmail.com"
password = getpass.getpass()
directory = username + surname + '/'
def download_emails(server):
    result, data = server.uid('search', None, "ALL")    #search all email and return their uids
    if result == 'OK':
        for num in data[0].split():
            result, data = server.uid('fetch', num, '(RFC822)')    #RFC is a standard for the format of ARPA Internet text messages
            if result == 'OK':
                email_message = email.message_from_bytes(data[0][1])    #raw email text including headers
                file_name = email_message['Subject']       #use dates and file names(can be changed)
                if not os.path.exists(directory):
                    os.makedirs(directory)      #create a dir for user's emails
                try:
                    email_file = open(directory + file_name+'.eml', 'wb')   #open a file for each email and insert the data.
                    email_file.write(data[0][1])
                    email_file.close()
                except:
                    pass

#function to zip all the emails
def archive(zipname, directory):
    return shutil.make_archive(zipname, 'zip', root_dir=directory, base_dir=None)

#function to upload zipped emails to AWS bucket
def upload_to_s3(file_name):
    s3 = boto3.resource('s3',
                aws_access_key_id=accessKey,
                aws_secret_access_key=secretKey,
                aws_session_token=secretToken,
                )

    s3.Bucket('user-backups').put_object(Key=username.title() + " " +
                                surname.title() + "/" + file_name, Body=file_name)
    print("Uploaded")


def main():
    server = imaplib.IMAP4_SSL("imap.gmail.com", 993)   #connect to gmail's imap server
    server.login(email_address, password)   #enter creds
    result, data = server.select('"[Gmail]/All Mail"')  #get all emails(inbox, outbox etc)
    if result == 'OK':
        print("Downloading")
        download_emails(server)
        server.close()
    else:
        print("ERROR: Unable to open mailbox ", result)
    server.logout()
    archive(username + surname, directory)
    upload_to_s3(username + surname + ".zip")
    #os.remove(email_address + ".zip")
    #shutil.rmtree(email_address)
    print("Done")
if __name__ == "__main__":
    main()

【问题讨论】:

    标签: python amazon-s3 boto3


    【解决方案1】:

    您可以查看此article 了解更多信息。

    有多种上传方式。看看这个boto3 document,我有下面列出的方法:

    The managed upload methods are exposed in both the client and resource interfaces of boto3:
    
    S3.Client method to upload a file by name: S3.Client.upload_file()
    S3.Client method to upload a readable file-like object: S3.Client.upload_fileobj()
    S3.Bucket method to upload a file by name: S3.Bucket.upload_file()
    S3.Bucket method to upload a readable file-like object: S3.Bucket.upload_fileobj()
    S3.Object method to upload a file by name: S3.Object.upload_file()
    S3.Object method to upload a readable file-like object: S3.Object.upload_fileobj()
    

    我使用s3.client.upload_file 使它工作。

    upload_file(文件名、存储桶、密钥、ExtraArgs=None、Callback=None、 配置=无)。
    将文件上传到 S3 对象。

    import boto3
    s3Resource = boto3.resource('s3')
    
    try: 
        s3Resource.meta.client.upload_file('/path/to/file', 'bucketName', 'keyName')
    except Exception as err:
        print(err)
    

    【讨论】:

      【解决方案2】:

      put_object 函数接受 Body,它可以是字节对象或文件对象。您当前刚刚传递了纯文件名(字符串)。

      来自文档:

      正文(字节或可查找的类似文件的对象)——对象数据。

      所以修复应该是传递文件对象。请咨询this 了解如何操作。

      【讨论】:

      • 问题是它以 .zip 文件的形式上传。我的目录中有一个 23MB 大小的 zip 文件。当我上传它时,它就像一个完全不同的文件。我在 upload_to_s3 中传递文件名 + 扩展名。
      • @davidb 试试这个并分享你的发现
      • @davidb 你能分享你如何使用 zipfile 上传的代码吗?看来我们必须知道压缩文件中的文件名才能做到这一点?
      【解决方案3】:

      只需使用s3.client.upload_file

      upload_file(文件名、存储桶、密钥、ExtraArgs=None、Callback=None、 配置=无)

      def upload_to_s3(file_name):
        s3 = boto3.client('s3')
        Key = username.title() + " " + surname.title() + "/" + file_name
        try: 
           s3.meta.client.upload_file('/path/to/file', 'user-backups', Key)
        except Exception as e:
           print(e)
      

      【讨论】:

        【解决方案4】:

        以上答案均无效!
        以下代码对我有用..

         import os 
         def upload_file_zip(s3_folder,local_file_path):
           s3_client = boto3.client('s3')
           s3_path = os.path.join(s3_folder, os.path.basename(local_file_path))
           with open(local_file_path,mode='rb') as data:
              s3_client.upload_fileobj(data, BUCKET_NAME, s3_path)
        

        【讨论】:

        • local_file_path 是 zip 文件吗?
        • 是的,它的 zip 文件
        猜你喜欢
        • 1970-01-01
        • 2018-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-09
        • 2021-09-23
        相关资源
        最近更新 更多