Express.js + AWS S3异步问题:POST提前返回200致下载异常
解决Express+AWS S3中POST返回时PDF未生成的问题
你的问题根源在于formHandler函数虽标记为async,但内部使用了S3回调式API,导致异步操作未被正确等待。当await formHandler(formData)执行时,s3.getObject的回调还未完成PDF填充与上传,函数就提前返回,POST接口先返回200,而S3中的文件尚未生成。
1. 重构formHandler模块,改用Promise式S3操作
将回调式的S3操作改为Promise形式,确保所有异步步骤都被await:
require("dotenv").config(); const AWS = require("aws-sdk"); const { PDFDocument } = require("pdf-lib"); const formHandler = async (formData) => { try { const s3 = new AWS.S3(); const downloadParams = { Bucket: process.env.BUCKET, Key: "forms/rawForm.pdf", }; // 改用Promise形式获取S3对象,替代回调 const form = await s3.getObject(downloadParams).promise(); const pdfFormBuffer = form.Body; // 等待PDF填充与上传完成 await fillOutPDFForm(pdfFormBuffer, formData, s3); } catch (err) { console.error("表单处理出错:", err); throw err; // 抛出错误让上层接口捕获 } }; const fillOutPDFForm = async (pdfFormBuffer, formData, s3) => { const pdfDoc = await PDFDocument.load(pdfFormBuffer); const form = pdfDoc.getForm(); // 此处填写表单填充业务逻辑 // 示例:form.getTextField('username').setText(formData.username); const modifiedPdfBuffer = await pdfDoc.save(); await saveModifiedPDFToS3(modifiedPdfBuffer, s3); }; const saveModifiedPDFToS3 = async (modifiedPdfBuffer, s3) => { const bufferData = Buffer.from(modifiedPdfBuffer); const uploadParams = { Bucket: process.env.BUCKET, Key: "output/preparedForm.pdf", Body: bufferData, }; await s3.upload(uploadParams).promise(); }; module.exports = formHandler;
2. 优化Express POST接口的错误处理
确保formHandler出错时,接口返回错误状态码,避免静默失败:
// FORM PREPARATION app.post("/form", async (req, res) => { try { const formData = req.body; // req.body无需await,express.json()已完成解析 await formHandler(formData); res.status(200).json({ status: "PDF created.", // 修正原代码中的"satus"拼写错误 }); } catch (err) { console.error("POST接口出错:", err); res.status(500).json({ error: "PDF生成失败,请重试" }); } });
额外优化建议
- 避免文件覆盖:当前所有用户生成的PDF共用同一个
preparedForm.pdf,会导致后续用户覆盖之前的文件。建议根据请求ID、时间戳或用户信息生成唯一文件名(如output/preparedForm-${Date.now()}.pdf),并在POST返回时将文件名传给前端,下载接口根据文件名获取对应文件。 - 完善下载接口错误提示:针对文件不存在的情况返回更友好的提示:
s3Stream.on("error", (err) => { if (err.code === 'NoSuchKey') { res.status(404).send("文件尚未生成,请稍后重试"); } else { console.error("Error downloading file from S3:", err); res.status(500).send("Error downloading file"); } });
内容的提问来源于stack exchange,提问作者Aslan
相关产品推荐
相关产品推荐

