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

生产环境上传PDF Buffer到S3时报首个参数类型不匹配错误

问题根因

报错本质是传入Buffer.from()的pdf参数不是合法的字符串/二进制类型,而是一个Error对象。
问题出在getPDFBuffer的错误处理逻辑:生产环境下chrome-aws-lambda生成PDF流程触发异常时,catch块直接return error,没有抛出错误,导致外层把Error实例当成正常的PDF Buffer传到了上传步骤,调用Buffer.from(error)时就触发了类型不匹配错误。
本地环境用原生puppeteer时PDF生成流程没有异常,能拿到正常Buffer,所以上传流程可以跑通。生产环境chrome-aws-lambda启动失败、依赖缺失、参数配置错误都可能导致PDF生成步骤抛错,被错误的catch逻辑吞掉后,就会触发你看到的上传报错。
另外原代码里还有两个隐藏问题:

  • waitForNavigation写在setContent之前,存在竞态,生产环境偶发会出现页面没加载完就生成PDF、甚至等待超时的问题
  • page.pdf()本身返回的就是Buffer类型,上传时不需要再额外调用Buffer.from()做转换
修复方案
  • 修正getPDFBuffer的错误处理,不要吞错,同时修复页面加载的竞态问题:
static getPDFBuffer = async (html, options) => {
  let browser = null;
  try {
    const executablePath = process.env.IS_OFFLINE
      ? null
      : await chromium.executablePath;
    browser = await chromium.puppeteer.launch({
      args: chromium.args,
      executablePath,
      headless: true,
      ignoreDefaultArgs: ['--disable-extensions']
    });

    const page = await browser.newPage();
    // 把等待逻辑合并到setContent配置中,解决竞态
    await page.setContent(html, {
      waitUntil: "load"
    });

    return await page.pdf({
      format: 'A4',
      printBackground: true,
      ...options
    });
  } catch (error) {
    console.error("PDF生成失败:", error);
    // 直接抛出错误,不要返回Error对象
    throw error;
  } finally {
    if (browser !== null) {
      await browser.close();
    }
  }
};
  • 调用getPDFBuffer的位置增加错误捕获,避免异常值流入后续流程:
let pdf;
try {
  pdf = await Helper.getPDFBuffer(html, options);
} catch (e) {
  throw new Error(`PDF生成失败:${e.message}`);
}

// 原有S3预签名URL生成逻辑保持不变
const merchantCod = params.merchantId;
const signedURLExpireSeconds = 60 * 10;
const rutaDocumento = params.folderMovement + "/"
const tipoDocumento = "facturaNro"
const extraRandomNumber = Math.floor(Math.random() * (10000 - 1)) + 1;
let nroDocumento = params.nro

const presignedS3UrlPDF = await  s3getSignedUrl("putObject", {
  Bucket: BUCKET_NAME,
  Key: "another/" + merchantCod + "/" + rutaDocumento + tipoDocumento + nroDocumento + "-" + extraRandomNumber+ ".pdf",
  Expires: signedURLExpireSeconds,
  ContentType: "application/pdf"
});
let resultUploadPDF = await uploadPDF(presignedS3UrlPDF, pdf);
  • 优化上传方法,增加类型校验,去掉冗余的Buffer转换:
static async uploadPDF(presignedS3Url, pdf){
  try {
    if (!Buffer.isBuffer(pdf) && typeof pdf !== 'string') {
      throw new Error(`待上传内容类型非法,实际类型:${typeof pdf}`);
    }
    // page.pdf已经返回Buffer,直接传入即可
    let resultado = await axios.put(presignedS3Url, pdf, {
      headers: {
          'Content-Type': 'application/pdf'
      }
    });
    return resultado.statusText;
  } catch (error) {
    console.log("PDF上传失败:", error)
    throw error;
  }
}
额外排查项

如果抛出的错误是chrome启动相关,优先检查:

  • Lambda运行内存是否至少配置为1024M,内存低于512M时chrome-aws-lambda大概率启动失败
  • chrome-aws-lambda和puppeteer-core版本是否匹配,部署包是否正确包含chrome二进制文件
  • Lambda执行角色是否有临时目录读写权限(chrome启动时需要在/tmp目录写临时文件)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:24:41