基于Lambda(Python)从S3读取CSV并通过API Gateway返回的实现问题
解决API Gateway + Lambda实现CSV自动下载的问题
原代码存在的问题
- 对
wr.s3.read_csv返回值处理有误:读取多CSV文件时返回的是DataFrame迭代器,嵌套循环逻辑会导致提前返回且未正确合并数据 - CSV格式返回缺少关键响应头:浏览器需通过响应头识别可下载文件,原代码未配置相关头部
- JSON返回格式不符合API Gateway要求:
body需为字符串而非解析后的JSON对象 - 状态码使用不规范:错误场景应返回标准HTTP状态码(如400表示参数错误)
修改后的Lambda代码
import json import awswrangler as wr import pandas as pd def lambda_handler(event, context): # 获取路径参数和查询参数 bucket_name = event['params']['path']['bucket'] fmt = event['params']['querystring']['fmt'].lower() full_path = f"s3://{bucket_name}" # 读取S3中所有CSV文件并合并为单个DataFrame try: dfs = list(wr.s3.read_csv(path=full_path, path_suffix=['.csv'], use_threads=True)) if not dfs: return { "statusCode": 404, "body": json.dumps({"error": "未找到CSV文件"}) } raw_df = pd.concat(dfs, ignore_index=True) except Exception as e: return { "statusCode": 500, "body": json.dumps({"error": f"读取S3文件失败: {str(e)}"}) } # 处理JSON格式请求 if fmt == 'json': json_data = raw_df.to_json(orient="records") return { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": json_data } # 处理CSV格式请求(触发自动下载) elif fmt == 'csv': csv_data = raw_df.to_csv(index=False) return { "statusCode": 200, "headers": { "Content-Type": "text/csv", "Content-Disposition": "attachment; filename=\"bucket-data.csv\"" }, "body": csv_data, "isBase64Encoded": False } # 处理无效格式参数 else: return { "statusCode": 400, "body": json.dumps({"error": "无效的格式参数,仅支持json/csv"}) }
关键说明
- 数据合并:将读取到的多个DataFrame合并为一个,避免数据片段化
- CSV下载触发:通过
Content-Disposition头指定为attachment并设置文件名,浏览器会自动识别为下载任务 - 响应头规范:为JSON和CSV分别配置对应
Content-Type,确保客户端正确解析内容 - 错误处理:增加文件不存在、读取失败、参数错误等场景的异常捕获,返回标准HTTP状态码
- 参数兼容:将
fmt转为小写,避免大小写敏感导致的格式识别失败
内容的提问来源于stack exchange,提问作者bob
相关产品推荐
相关产品推荐

