【问题标题】:Zipping files in s3 using AWS Lambda (Python)使用 AWS Lambda (Python) 在 s3 中压缩文件
【发布时间】:2021-07-17 16:41:39
【问题描述】:

我在 s3 存储桶中有几百个 PDF,我想要一个 lambda 函数来为我的所有 PDF 创建一个 zip 文件。

在我的本地 Python 上执行此操作显然很容易,我曾假设逻辑会以一种非常直接的方式转移到 AWS Lambda。但到目前为止,我还没有设法让这个工作。

我一直在使用 zipfile Python 库,以及 boto3。我的逻辑很简单,就是找到所有文件,将它们附加到“files_to_zip”列表中,然后遍历该列表,将每个文件写入新的 zip 文件。

然而,这引发了许多问题,我认为这是由于我对在 Lambda 中调用和加载文件的工作原理缺乏了解。

这是我目前尝试过的代码

    import os
    import boto3
    from io import BytesIO, StringIO
    from zipfile import ZipFile, ZIP_DEFLATED

    def zipping_files(event, context):
        s3 = boto3.resource('s3')

        BUCKET = 'BUCKET NAME'
        PREFIX_1 = 'KEY NAME'
        new_zip = r'NEW KEY NAME' 
        s3_client = boto3.client('s3')
        files_to_zip = []
        response = s3_client.list_objects_v2(Bucket=BUCKET, Prefix=PREFIX_1)

        all = response['Contents']     
        for i in all:
            files_to_zip.append(str(i['Key']))



        with ZipFile(new_zip, 'w',  compression=ZIP_DEFLATED, allowZip64=True) as new_zip:
            for file in files_to_zip:
                new_zip.write(file) 

我收到错误消息,例如我的 new_zip 字符串不存在 (FileNotFoundError),这是一个只读操作。

【问题讨论】:

    标签: python amazon-web-services amazon-s3 aws-lambda


    【解决方案1】:

    我们如何解决这个问题

    import os
    import boto3
    from io import BytesIO, StringIO
    from zipfile import ZipFile, ZIP_DEFLATED
    
    def zipping_files(event, context):
        s3 = boto3.resource('s3')
    
        BUCKET = 'BUCKET NAME'
        PREFIX_1 = 'KEY NAME'
        s3_client = boto3.client('s3')
        files_to_zip = []
        response = s3_client.list_objects_v2(Bucket=BUCKET, Prefix=PREFIX_1)
    
        all = response['Contents']     
        for i in all:
            files_to_zip.append(str(i['Key'])) 
    
        # we download all files to tmp directory of lambda for that we create directory structure in /tmp same as s3 files structure (subdirectory)
    
        for KEY in files_to_zip:
        try:
            local_file_name = '/tmp/'+KEY
            if os.path.isdir(os.path.dirname(local_file_name)):
              print(local_file_name)
            else:
              os.mkdir(os.path.dirname(local_file_name))
    
            s3_resource.Bucket(bucket).download_file(KEY, local_file_name)
        except botocore.exceptions.ClientError as e:
            print(e.response)
    
        #now create empty zip file in /tmp directory use suffix .zip if you want 
        with tempfile.NamedTemporaryFile('w', suffix='.tar.gz', delete=False) as f:
          with ZipFile(f.name, 'w', compression=ZIP_DEFLATED, allowZip64=True) as zip:
            for file in files_to_zip:
              zip.write('/tmp/'+file)
    
      #once zipped in temp copy it to your preferred s3 location 
      s3_resource.meta.client.upload_file(f.name, bucket, 'destination_s3_path ex. out/filename.tar.gz')
      print('All files zipped successfully!')
    

    【讨论】:

    • 我收到 NameError: name 'botocore' is not defined
    【解决方案2】:

    此代码示例尝试在 Lambda 函数容器的本地文件系统的默认目录(/var/taskafaik)中创建一个本地文件 NEW KEY NAME

    第1步:在/tmp目录下创建一个像样的文件路径,即os.path.join('/tmp', target_filename)

    第 2 步:您的代码没有将 zip 文件上传到 S3。添加对s3_client.put_object的呼叫。

    【讨论】:

      猜你喜欢
      • 2019-05-03
      • 2018-10-22
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 2018-11-02
      • 2018-11-27
      • 2021-02-12
      相关资源
      最近更新 更多