繁体   English   中英

使用 AWS Lambda (Python) 在 s3 中压缩文件

[英]Zipping files in s3 using AWS Lambda (Python)

我在 s3 存储桶中有几百个 PDF,我想要一个 lambda function 为我的所有 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),这是一个只读操作。

在这里我们如何解决这个问题

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_client.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_client.meta.client.upload_file(f.name, bucket, 'destination_s3_path ex. out/filename.tar.gz')
  print('All files zipped successfully!')

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

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

第 2 步:您的代码没有将 zipfile 上传到 S3。 添加对s3_client.put_object的调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM