本地正常的API控制器部署为Lambda后下载Zip文件损坏
AWS Lambda部署后Zip文件下载损坏问题解决
本地运行正常的API控制器,部署为AWS Lambda函数后,下载的Zip文件损坏。尝试流式传输响应,本地正常但AWS环境下依旧无效,且AWS CloudWatch未捕获到任何错误,下载的Zip文件仍损坏。相关代码如下:
export const downloadFiles3 = async (req: Request, res: Response) => { const key = req.params.key; try { const getObjectParams = { Bucket: process.env.AWS_BUCKET || '', Key: key, }; const data = await s3.getObject(getObjectParams).promise(); res.setHeader('Content-Type', 'application/zip'); res.setHeader('Content-Disposition', `attachment; filename=${key}`); res.send(data.Body); console.log('File sent successfully.'); } catch (error) { if (!res.headersSent) { if (error instanceof Error) { console.log('Error retrieving file content:', error); res.status(500).json({ message: 'Error retrieving file content', error: error.message, }); } else { console.log('Unexpected error:', error); res.status(500).json({ message: 'Unexpected error', error: String(error), }); } } else { console.log('Response headers already sent:', error); } } };
问题根源
本地环境和Lambda+API Gateway架构的响应处理逻辑存在差异:Lambda返回的二进制内容必须进行base64编码,同时要在响应中标记isBase64Encoded: true,否则API Gateway会将二进制数据当作纯文本解析,导致文件编码错乱损坏。
修复方案
1. 调整Lambda响应格式
Lambda的输入输出规范和Express的req/res模型不同,需要直接构造符合要求的响应对象:
export const downloadFiles3 = async (event: any) => { const key = event.pathParameters.key; try { const getObjectParams = { Bucket: process.env.AWS_BUCKET || '', Key: key, }; const data = await s3.getObject(getObjectParams).promise(); return { isBase64Encoded: true, statusCode: 200, headers: { 'Content-Type': 'application/zip', 'Content-Disposition': `attachment; filename=${key}` }, body: data.Body.toString('base64') }; } catch (error) { console.error('Error retrieving file content:', error); return { statusCode: 500, body: JSON.stringify({ message: 'Error retrieving file content', error: error instanceof Error ? error.message : String(error) }) }; } };
2. 配置API Gateway支持二进制类型
- 控制台配置:进入API Gateway对应API的设置页面,在「二进制媒体类型」中添加
application/zip - Serverless Framework配置:在
serverless.yml中添加:provider: apiGateway: binaryMediaTypes: - 'application/zip'
3. 若使用serverless-http插件适配Express
需在初始化时指定支持的二进制类型:
import serverless from 'serverless-http'; import app from './app'; export const handler = serverless(app, { binary: ['application/zip'] });
内容的提问来源于stack exchange,提问作者Shaheer Khalid
相关产品推荐
相关产品推荐

