Serverless Framework:上传至S3的二进制文件损坏问题
解决Busboy解析后S3上传二进制文件损坏的问题
我之前在做Serverless+S3上传的时候也踩过这个坑,二进制文件损坏大概率是编码处理或者API Gateway的配置问题,结合你的代码场景,给你几个靠谱的解决方案:
解决方案1:配置API Gateway支持二进制数据
这是最常见的原因——如果没配置API Gateway的二进制媒体类型,它会把所有请求体当成UTF-8文本处理,直接破坏二进制文件的字节结构。
在你的serverless.yml里添加以下配置:
provider: apiGateway: binaryMediaTypes: - '*/*' # 或者更精确地指定你需要的类型,比如image/*, application/pdf, text/plain
配置后重新部署服务,API Gateway就会正确传递二进制数据,不会做额外的编码转换。
解决方案2:改用流式上传到S3(推荐)
手动拼接Buffer不仅容易出编码问题,还会占用更多内存(尤其是大文件)。直接把Busboy的文件流传给S3的上传接口,能从根源避免这类问题:
const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const Busboy = require('busboy'); // 处理请求的核心逻辑 exports.handler = async (event) => { return new Promise((resolve, reject) => { const busboy = new Busboy({ headers: event.headers }); busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { // 直接将Busboy的文件流作为S3上传的Body const uploadParams = { Bucket: '你的S3桶名称', Key: filename, Body: file, ContentType: mimetype }; s3.upload(uploadParams, (err, data) => { if (err) { console.error('上传失败:', err); reject({ statusCode: 500, body: '上传失败' }); } else { console.log('上传成功:', data.Location); resolve({ statusCode: 200, body: JSON.stringify({ url: data.Location }) }); } }); }); // 处理Base64编码的请求体 let body = event.body; if (event.isBase64Encoded) { // 清理Base64中的换行/空格(部分网关可能会自动添加) body = body.replace(/\s/g, ''); } busboy.write(body, event.isBase64Encoded ? 'base64' : 'binary'); busboy.end(); }); };
这种流式处理的方式既高效又能避免Buffer拼接可能带来的编码错误。
解决方案3:修正Buffer拼接的预处理逻辑
如果你坚持要手动拼接Buffer,需要确保Base64数据的预处理是正确的:
let buffers = []; file.on('data', data => { // 确保每个chunk都是Buffer类型(避免意外的字符串转换) if (typeof data === 'string') { buffers.push(Buffer.from(data, 'binary')); } else { buffers.push(data); } }); file.on('end', () => { result.filename = filename; result.contentType = mimetype; // 拼接Buffer时指定编码(如果需要) result.file = Buffer.concat(buffers); }); // 预处理请求体 let body = event.body; if (event.isBase64Encoded) { body = body.replace(/\s/g, ''); // 去除Base64中的空白字符 } busboy.write(body, event.isBase64Encoded ? 'base64' : 'binary');
这里的关键是清理Base64中的空白字符,并且确保每个数据块都是Buffer类型,避免字符串编码转换破坏二进制数据。
内容的提问来源于stack exchange,提问作者Eric Barbour
相关产品推荐
相关产品推荐

