NestJS中AWS S3读取流未关闭引发超时错误的解决方法
问题解决:NestJS中ZIP生成请求超时(流未正确关闭)
你遇到的Error [TimeoutError]: Connection timed out after 120000ms,本质是处理S3文件流与archiver压缩流时,未正确关闭所有流资源,导致Promise一直处于pending状态,请求无法正常结束。以下是针对性的修复方案:
核心修复逻辑:确保所有流闭环并触发Promise resolve
1. 完整处理archiver与S3上传流的生命周期
使用archiver生成ZIP时,必须监听finish事件,主动调用archiver.finalize(),同时绑定S3上传流的close/error事件,确保所有流完成后再resolve Promise。
2. 主动销毁异常或已完成的S3下载流
从S3获取PDF的读流出现错误,或流使用完成后,需主动调用stream.destroy()释放资源,避免流占用导致Promise无法收尾。
修复后的关键代码示例
async function generateAndUploadZip(s3Client: S3, pdfKeys: string[], zipKey: string): Promise<string> { return new Promise((resolve, reject) => { const archive = archiver('zip', { zlib: { level: 6 } }); const uploadParams = { Bucket: process.env.S3_BUCKET, Key: zipKey, Body: archive, }; // 绑定S3上传流事件 const uploadStream = s3Client.upload(uploadParams); uploadStream.on('error', (err) => { archive.destroy(); reject(err); }); // 绑定archiver事件 archive.on('error', (err) => { uploadStream.abort(); reject(err); }); archive.on('finish', () => { uploadStream.send() .then(data => resolve(data.Location)) .catch(reject); }); // 批量添加PDF文件到ZIP for (const key of pdfKeys) { const getObjectParams = { Bucket: process.env.S3_BUCKET, Key: key }; const pdfStream = s3Client.getObject(getObjectParams).createReadStream(); pdfStream.on('error', (err) => { archive.destroy(); uploadStream.abort(); reject(err); }); archive.append(pdfStream, { name: `${key.split('/').pop()}` }); } // 启动压缩并关闭archiver archive.finalize(); }); }
额外注意事项
- 所有流的
error事件必须监听,未捕获的流错误会直接导致Promise pending - NestJS控制器中需确保返回的Promise正确resolve/reject,框架会自动结束请求
- ZIP文件已存在的分支逻辑需独立处理,避免不必要的流操作引发资源泄漏
内容的提问来源于stack exchange,提问作者Izlia
相关产品推荐
相关产品推荐

