AWS Lambda传输图片Buffer至Discord时损坏,本地正常部署异常求助
解决AWS Lambda传递图片Buffer至Discord/Webhook时损坏的问题
核心问题定位
你的图片Buffer损坏的根本原因是Busboy解析文件数据流时未正确累加所有分块数据:本地测试时图片数据量小,可能一次性完成传输,data事件仅触发一次,result.file = data能拿到完整数据;但部署到AWS后,API Gateway会将较大请求分块传输,data事件多次触发,每次赋值都会覆盖之前的内容,最终只保留最后一块数据,导致图片不完整(本地文件比Lambda版本大50字节就是这个原因)。
修复步骤
1. 修正Busboy的文件数据累加逻辑
修改解析器代码中file.on('data')的处理逻辑,将分块数据累加后合并为完整Buffer:
const Busboy = require('busboy'); const getContentType = (event: any) => { const contentType = event.headers['content-type']; if (!contentType) { return event.headers['Content-Type']; } return contentType; }; export const parser = (event: any) => new Promise((resolve, reject) => { const busboy = new Busboy({ headers: { 'content-type': getContentType(event) } }); let result: any = { file: [], // 用数组存储分块数据 filename: '', contentType: '' }; busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { file.on('data', (data) => { result.file.push(data); // 累加每一块数据 }); file.on('end', () => { // 将分块数组合并为完整Buffer result.file = Buffer.concat(result.file); result.filename = filename; result.contentType = mimetype; }); }); busboy.on('field', (fieldname, value) => { result[fieldname] = value; }); busboy.on('error', (error: any) => reject(error)); busboy.on('finish', () => { event.body = result; resolve(event); }); busboy.write(event.body, event.isBase64Encoded ? 'base64' : 'binary'); busboy.end(); });
2. 完善API Gateway二进制配置
确保API Gateway正确处理multipart/form-data类型的请求(FormData上传必须配置),更新serverless.yml:
custom: apigwBinary: types: - 'image/png' - 'multipart/form-data' # 新增:FormData请求需设为二进制类型 provider: apiGateway: binaryMediaTypes: - 'image/png' - 'multipart/form-data' functions: sendImageToDiscord: handler: src/handler.sendImageToDiscord events: - http: path: /post-image method: post cors: true
部署后可在AWS控制台API Gateway页面,检查对应API的「Binary Media Types」是否包含上述类型。
3. 确认Discord上传逻辑正确性
确保postImageTableToDiscord函数正确传递完整Buffer,示例如下:
import axios from 'axios'; import FormData from 'form-data'; async function postImageTableToDiscord(fileBuffer: Buffer, assetType?: string) { const formData = new FormData(); formData.append('file', fileBuffer, { filename: 'file.png', contentType: 'image/png' }); await axios.post('YOUR_DISCORD_WEBHOOK_URL', formData, { headers: { ...formData.getHeaders() } }); }
额外验证点
- 查看CloudWatch日志中打印的Buffer长度,确认和本地生成的图片文件大小一致,验证数据传递完整性;
- 无需保留3秒延迟,竞态条件不是问题根源。
内容的提问来源于stack exchange,提问作者user6680
相关产品推荐
相关产品推荐

