使用Node.js通过预签名URL上传.tar.gz至S3失败问题排查
问题分析与解决方案
核心问题点
Content-Length计算错误:
你用new Blob([data]).size计算内容长度,但在Node.js环境中,fs.readFileSync返回的是Buffer,直接用data.length就能得到正确的字节数。用Blob计算可能导致长度不匹配,S3会因为内容实际长度与请求头声明的不一致,静默拒绝上传(无错误提示但不完成上传)。Content-Encoding头设置错误:
.tar.gz是已经经过gzip压缩的文件,你设置Content-Encoding: gzip会让S3认为你上传的是未压缩内容经过gzip编码传输,S3会自动尝试解压内容后存储。这与你要上传压缩文件本身的需求冲突,导致上传流程异常中断。
修正后的代码
const tarFile = '/tmp/some.tar.gz'; const data = fs.readFileSync(tarFile); const req = https.request( url, { method: 'PUT', headers: { 'Content-Length': data.length, // 直接用Buffer的length获取正确字节数 'Content-Type': 'application/x-gzip', // 仅保留文件类型头 // 移除Content-Encoding: gzip }, }, (res) => { let responseBody = ''; res.on('data', (chunk) => { responseBody += chunk; }); res.on('end', () => { console.log({ responseBody, statusCode: res.statusCode }); // 额外打印状态码便于排查 }); } ); req.on('error', (err) => { console.error('上传错误:', err); reject(err); }); req.write(data); req.end();
额外排查建议
- 打印响应的
statusCode:通过res.statusCode可以获取S3返回的状态码,比如400(请求错误)、403(权限问题)等,帮助快速定位问题。 - 检查预签名URL的有效期和权限:确保预签名URL未过期,且包含
PUT操作的权限。 - 验证文件完整性:确认
/tmp/some.tar.gz文件本身无损坏,可以本地解压测试。
内容的提问来源于stack exchange,提问作者gagan
相关产品推荐
相关产品推荐

