You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Node.js等待pdf.on('end')中S3文件上传完成?

解决S3上传完成前返回元数据导致的文件访问404问题

你的问题核心在于:pdf.on('end')的异步回调并没有被当前流程等待,pdf.end()执行后直接就生成签名URL并返回了元数据,这时候S3的上传操作还在后台运行,自然会出现文件未上传完成就访问导致的404,日志顺序也印证了这点——Finished with pdf:先输出,之后才是S3 Upload Success。

要让整个流程等待S3上传完成,最可靠的方式是把end事件的处理逻辑包装成Promise,用await等待它执行完毕,再进行后续的签名URL生成和返回操作。修改后的代码如下:

// 将pdf的end事件和S3上传包装成Promise
await new Promise(async (resolve) => {
  pdf.on('end', async () => {
    const result = Buffer.concat(chunks);
    await s3.putObject({
      Bucket: 'corp-attch',
      Key: filePath,
      Body: result,
      ContentType: 'application/pdf',
    }).promise();
    this.logger.log(`S3 Upload Success:  ${filePath}`);
    resolve(); // 上传完成后resolve这个Promise
  });

  await pdf.end();
});

this.logger.log(`Finished with pdf:  ${filePath}`);
returnAttach.attachDest = filePath;
returnAttach.attachName = filePath.split('/').pop();
const getObjectParams = {
  Bucket: this.configService.awsCorpBucketName,
  Key: filePath, 
  Expires: 900,
};

returnAttach.attachUrl = s3.getSignedUrl('getObject', getObjectParams);
return returnAttach;

关键改动说明

  • 把原来的pdf.on('end')和pdf.end()逻辑放进一个新的Promise里,只有当S3上传完成并调用resolve()后,这个Promise才会完成
  • 用await等待这个Promise,确保后续生成签名URL、返回元数据的操作,都在S3上传完成之后执行
  • 最后直接返回returnAttach即可,不需要额外包装一层Promise(当前函数应为async函数,直接返回值会自动被包装成Promise)

这样修改后,日志顺序会变成先输出S3 Upload Success,再输出Finished with pdf:,生成的签名URL访问时文件已经存在于S3,就不会出现404了。

内容的提问来源于stack exchange,提问作者RenControl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:43:18