如何用Python Lambda流式压缩S3文件并上传至另一S3存储桶
基于流式处理的S3到S3实时压缩Lambda实现
嘿,我完全懂你遇到的问题——Lambda那500MB的/tmp存储确实不够用,而且磁盘IO不仅拖慢性能,还可能在处理大文件时触发限制。流式处理绝对是最优解,全程在内存中读写数据,完全不用落地到磁盘。下面是一个完整的Python端到端实现,涵盖所有必要细节:
核心思路
我们会用boto3的流式API直接读取源S3对象的内容,通过Python的gzip库实时压缩数据流,最后再通过流式API上传到目标S3桶。整个过程没有任何磁盘写入操作,完全依赖内存流处理。
完整代码实现
import boto3 import gzip import io import os # 从环境变量获取目标桶名(推荐用环境变量,避免硬编码) TARGET_BUCKET = os.environ.get('TARGET_S3_BUCKET') s3_client = boto3.client('s3') def lambda_handler(event, context): # 解析S3触发事件 for record in event['Records']: source_bucket = record['s3']['bucket']['name'] source_key = record['s3']['object']['key'] # 生成目标键(这里给原文件名加上.gz后缀,你可以自定义规则) target_key = f"{source_key}.gz" try: # 1. 获取源S3对象的流式响应(不下载整个文件到本地) response = s3_client.get_object(Bucket=source_bucket, Key=source_key) source_stream = response['Body'] # 2. 创建内存压缩流:将源流的数据实时压缩 # 使用io.BytesIO作为缓冲,配合gzip.GzipFile实现流式压缩 compressed_stream = io.BytesIO() with gzip.GzipFile(fileobj=compressed_stream, mode='wb', compresslevel=9) as gz: # 分块读取源流,避免一次性加载大文件到内存 chunk_size = 1024 * 1024 # 1MB chunks,可根据内存调整 while True: chunk = source_stream.read(chunk_size) if not chunk: break gz.write(chunk) # 重置压缩流的指针到开头,准备上传 compressed_stream.seek(0) # 3. 流式上传压缩后的内容到目标桶 s3_client.upload_fileobj( Fileobj=compressed_stream, Bucket=TARGET_BUCKET, Key=target_key, ExtraArgs={'ContentType': 'application/gzip'} ) print(f"成功压缩并上传:{source_bucket}/{source_key} -> {TARGET_BUCKET}/{target_key}") except Exception as e: print(f"处理文件时出错:{str(e)}") raise e
关键配置说明
1. Lambda触发配置
- 给你的Lambda函数添加S3触发器,选择源存储桶,触发事件类型为
All object create events(或者更精确的Put事件)。 - 注意:如果源桶和Lambda不在同一区域,需要在触发器配置中指定正确的区域。
2. 环境变量设置
在Lambda的配置页面,添加环境变量TARGET_S3_BUCKET,值为你的目标存储桶名称,这样不用硬编码在代码里,更灵活。
3. IAM权限配置
确保Lambda的执行角色拥有以下权限(可以通过IAM策略添加):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的源桶名称/*" }, { "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::你的目标桶名称/*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" } ] }
4. Lambda性能调优
- 内存设置:Lambda的内存越大,分配的CPU和网络带宽越高,处理大文件时建议设置为1024MB或更高,提升流式处理速度。
- 超时时间:根据你处理的文件大小调整,比如处理1GB的文件,可能需要设置5-10分钟的超时(Lambda最大支持15分钟)。
- 压缩级别:代码中
compresslevel=9是最高压缩比,如果你更看重速度,可以改成compresslevel=1(最快压缩,压缩比稍低)。
测试验证
- 上传一个测试文件到源存储桶。
- 查看Lambda的CloudWatch日志,确认没有报错,且输出了成功的日志信息。
- 检查目标存储桶,确认生成了对应的
.gz压缩文件,下载解压后验证内容和原文件一致。
内容的提问来源于stack exchange,提问作者Manoj Dhake
相关产品推荐
相关产品推荐

