使用Node.js的AWS Lambda从Ajax传图至S3时文件损坏求助
解决Ajax上传图片到Lambda+S3后文件损坏的问题
我之前处理过几乎一模一样的场景,图片上传后损坏的核心原因是你在Busboy中处理文件数据时,只保留了最后一段Buffer片段,没有完整拼接所有数据。咱们来一步步修复:
问题根源
在你的Parser函数里,file.on('data')事件会多次触发(大文件会被分片传输),而你直接用result.file = data覆盖之前的内容,最终只保存了最后一小段数据,导致图片文件不完整自然损坏。
修复步骤
1. 修正Parser函数中的文件数据拼接逻辑
把原来的单个Buffer赋值改成数组收集所有片段,最后合并成完整的Buffer:
const parser = (event) => new Promise((resolve, reject) => { const busboy = new Busboy({ headers: { 'content-type': getContentType(event) } }); const result = {}; // 初始化数组来收集所有文件数据片段 result.fileChunks = []; busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { file.on('data', data => { // 将每个数据片段push到数组中 result.fileChunks.push(data); }); file.on('end', () => { // 合并所有片段成完整的Buffer result.file = Buffer.concat(result.fileChunks); result.filename = filename; result.contentType = mimetype; // 清理临时数组 delete result.fileChunks; }); }); busboy.on('field', (fieldname, value) => { result[fieldname] = value; }); busboy.on('error', error => reject(error)); busboy.on('finish', () => { event.body = result; resolve(event); }); // 确保正确处理base64编码的body const bodyBuffer = event.isBase64Encoded ? Buffer.from(event.body, 'base64') : event.body; busboy.write(bodyBuffer); busboy.end(); });
2. 完善S3上传的参数配置
在uploadPropertyImage函数中显式指定ContentType参数,避免浏览器无法正确识别图片类型(虽然S3会自动检测,但显式设置更稳妥):
const uploadPropertyImage = (buffer, fileName, contentType) => new Promise((resolve, reject) => { const bucketName = "BUCKET-NAME"; var filePath = `${fileName}`; const data = { Bucket: bucketName, Key: filePath, Body: buffer, ACL: 'public-read', ContentType: contentType // 新增:显式设置文件类型 }; s3.upload(data, (error, data) => { if (!error) { resolve(data.Location); } else { reject(new Error(`上传失败: ${error.message}`)); } }); });
3. 更新Handler中的调用逻辑
记得把文件类型参数也传给上传函数:
parser(event).then(() => { var request = event.body; if (request.operation == "uploadImage") { uploadPropertyImage(request.file, request.filename, request.contentType) .then((result) => { // 处理成功逻辑 console.log('图片上传成功:', result); }).catch((err) => { // 处理错误 console.error('上传错误:', err); }); } });
额外检查点
- 确认API Gateway的集成请求设置中,
Content Handling配置为CONVERT_TO_BINARY(如果是使用Lambda代理集成),避免base64编码转换出现问题。 - 测试时可以打印
request.file.length,对比本地文件的大小,确保数据长度一致。
这样修改后,上传的图片就能完整保存到S3了。
内容的提问来源于stack exchange,提问作者Nagesh
相关产品推荐
相关产品推荐

