通过单次触发Lambda将S3中Zip文件内容分发至多个CloudFront URL
解决方案概述
完全可以实现你的需求,核心流程是:当Zip文件上传到指定S3存储桶时自动触发Lambda函数,Lambda完成Zip解压后将内部资源同步到关联CloudFront的目标S3存储桶/路径,最终通过对应CloudFront URL访问这些资源。
步骤1:配置S3自动触发Lambda
- 创建或复用Lambda函数(推荐用Python/Node.js,处理Zip解压逻辑更便捷)
- 在Lambda控制台的「触发器」模块添加S3触发器:
- 选择存放Zip文件的源S3桶
- 触发事件类型选择
s3:ObjectCreated:*,若需仅触发Zip文件上传,可在「过滤条件」中添加后缀.zip - 为Lambda执行角色配置精细权限(避免过度授权):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的源Zip存储桶/*" }, { "Effect": "Allow", "Action": "s3:PutObject", "Resource": [ "arn:aws:s3:::CloudFront关联桶1/*", "arn:aws:s3:::CloudFront关联桶2/*" ] }, { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:你的区域:你的账号ID:*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:你的区域:你的账号ID:log-group:/aws/lambda/你的Lambda函数名:*" } ] }
步骤2:Lambda核心逻辑实现
以Python为例,核心功能包括下载Zip、解压、按规则分发文件到对应CloudFront关联桶:
import boto3 import zipfile import os import traceback s3 = boto3.client('s3') # 定义文件与目标CloudFront关联桶的映射规则 FILE_TO_BUCKET_MAP = { "a.jpg": "cloudfront-bucket-1", "b.jpg": "cloudfront-bucket-2", "c.jpg": "cloudfront-bucket-1", # 可根据文件名前缀、类型扩展规则,比如所有png文件到bucket-3 } DEFAULT_TARGET_BUCKET = "default-cloudfront-bucket" def lambda_handler(event, context): try: # 提取S3上传事件中的文件信息 record = event['Records'][0]['s3'] source_bucket = record['bucket']['name'] zip_object_key = record['object']['key'] # 下载Zip到Lambda临时存储(上限512MB,超量需挂载EFS) zip_local_path = f"/tmp/{os.path.basename(zip_object_key)}" s3.download_file(source_bucket, zip_object_key, zip_local_path) # 解压Zip到临时目录 extract_dir = "/tmp/unzipped" os.makedirs(extract_dir, exist_ok=True) with zipfile.ZipFile(zip_local_path, 'r') as zip_ref: zip_ref.extractall(extract_dir) # 遍历解压后的文件,按规则上传到目标桶 for root, _, files in os.walk(extract_dir): for filename in files: local_file_path = os.path.join(root, filename) # 匹配目标桶,无匹配则用默认桶 target_bucket = FILE_TO_BUCKET_MAP.get(filename, DEFAULT_TARGET_BUCKET) # 上传文件,保持原文件名作为S3键(确保CloudFront URL对应) s3.upload_file(local_file_path, target_bucket, filename) # 清理临时文件(可选,Lambda执行完会自动清空/tmp) os.remove(zip_local_path) for root, _, files in os.walk(extract_dir): for f in files: os.remove(os.path.join(root, f)) os.rmdir(extract_dir) return {"statusCode": 200, "body": "Zip解压分发完成"} except Exception as e: # 记录错误日志到CloudWatch print(f"执行失败: {str(e)}") print(traceback.format_exc()) return {"statusCode": 500, "body": f"执行失败: {str(e)}"}
步骤3:CloudFront关联目标S3桶
- 为每个目标S3桶创建CloudFront分发:
- 源设置选择对应的S3存储桶(推荐使用OAI访问控制,避免S3直接公开访问)
- 默认缓存行为配置允许
GET/HEAD请求,按需设置缓存策略 - 等待CloudFront部署完成后,即可通过其域名访问对应文件(如
https://xxx.cloudfront.net/a.jpg)
关键注意事项
- Zip大小限制:Lambda默认临时存储为512MB,若Zip文件超量,需为Lambda挂载Amazon EFS扩展存储
- 分发规则扩展:可通过文件名前缀(如
img-*)、文件类型(如.png)等逻辑批量匹配目标桶,无需逐个文件配置 - 错误处理:Lambda中需添加异常捕获,将错误日志输出到CloudWatch,便于排查问题
- CloudFront缓存:若需新文件立即生效,可在Lambda中添加CloudFront缓存失效逻辑(需额外配置IAM权限)
内容的提问来源于stack exchange,提问作者Prathap Parameswar
相关产品推荐
相关产品推荐

