Node.js AWS Lambda远程PDF上传S3后文件空白问题求助
解决Lambda中下载PDF上传S3后文件空白的问题
我之前也碰到过Lambda里上传PDF到S3后文件空白的问题,大概率是你没处理好二进制数据的获取或者异步流程,给你几个实用的解决方案:
问题根源
- 二进制数据处理错误:
request库默认会把响应体按UTF-8字符串解析,但PDF是二进制文件,直接传字符串会导致数据损坏,最终生成空白文件 - 异步流程未收尾:Lambda函数如果在下载/上传操作完成前就提前结束,会导致S3只收到空数据
修复方案1:修改request配置,获取二进制Buffer
直接在request请求里添加encoding: null,让它返回原始二进制Buffer,再传给S3:
const request = require('request') const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const viewUrl = "https://link_to_downloadable_pdf/"; exports.handler = (event, context, callback) => { // 关键:设置encoding: null获取二进制Buffer request({ url: viewUrl, encoding: null }, (err, response, body) => { if (err) { console.error('PDF下载失败:', err); callback(err); return; } // 先检查响应状态码,确保PDF确实下载成功 if (response.statusCode !== 200) { const error = new Error(`下载失败,状态码:${response.statusCode}`); callback(error); return; } const s3Params = { Bucket: '你的S3桶名称', Key: '上传后的文件名.pdf', Body: body, // 这里的body是二进制Buffer ContentType: 'application/pdf', // 可选:设置下载时的文件名 ContentDisposition: 'attachment; filename="上传后的文件名.pdf"' }; s3.putObject(s3Params, (err, data) => { if (err) { console.error('S3上传失败:', err); callback(err); } else { console.log('上传成功:', data); callback(null, data); } }); }); };
修复方案2:用Async/Await简化异步流程(推荐)
如果觉得回调嵌套太麻烦,可以用request-promise-native(Promise版的request)配合async/await,代码更清晰,也更容易处理异步:
首先在本地安装依赖:
npm install request-promise-native
然后修改Lambda代码:
const request = require('request-promise-native'); const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const viewUrl = "https://link_to_downloadable_pdf/"; exports.handler = async (event) => { try { // 获取二进制Buffer const pdfBuffer = await request({ url: viewUrl, encoding: null }); const s3Params = { Bucket: '你的S3桶名称', Key: '上传后的文件名.pdf', Body: pdfBuffer, ContentType: 'application/pdf' }; // 上传到S3 await s3.putObject(s3Params).promise(); return { statusCode: 200, body: JSON.stringify({ message: 'PDF上传成功' }) }; } catch (err) { console.error('处理失败:', err); return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; } };
修复方案3:流方式上传(适合大文件)
如果PDF文件很大,用流的方式直接把下载的数据流传给S3,避免把整个文件加载到内存,减少Lambda的内存占用:
const request = require('request'); const AWS = require('aws-sdk'); const s3 = new AWS.S3(); const viewUrl = "https://link_to_downloadable_pdf/"; exports.handler = (event, context, callback) => { const s3Params = { Bucket: '你的S3桶名称', Key: '上传后的文件名.pdf', Body: request({ url: viewUrl, encoding: null }), // 直接传请求流 ContentType: 'application/pdf' }; s3.upload(s3Params, (err, data) => { if (err) { console.error('S3上传失败:', err); callback(err); } else { console.log('上传成功:', data); callback(null, data); } }); };
额外注意事项
- 调整Lambda的超时时间:如果PDF比较大,下载+上传可能需要几分钟,记得把Lambda的超时时间设长一点(比如5-10分钟)
- 检查S3权限:确保Lambda的执行角色有
s3:PutObject权限,避免因为权限问题导致上传不完整 - 验证下载的PDF:可以在代码里打印
body.length,确认拿到的Buffer长度不为0,说明确实下载到了数据
内容的提问来源于stack exchange,提问作者Craig Fox
相关产品推荐
相关产品推荐

