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

使用bwip-js生成PNG Buffer后,PDFKit报未知图片格式错误

问题解决:bwip-js生成PNG插入PDFkit报"Unknown image format"错误

问题描述

使用bwip-js生成条形码(返回PNG格式Buffer),通过fs.writeFile保存为PNG文件后,用pdfkit插入该图片时提示"Unknown image format",但本地文件管理器可正常打开图片,修改后缀为.PNG也无法解决问题。原代码如下:

const PDFDocument = require("pdfkit");
const bwipjs = require("bwip-js");
const fs = require("fs");

function generateCustomerInvoice(data) {
  const id = "12345678"
  bwipjs
    .toBuffer({
      bcid: "code128",
      text: id,
      scale: 3,
      height: 10,
      includetext: true,
      textxalign: "center",
    })
    .then((png) => {
      fs.writeFile("./barcodes/" + id + ".png", png, () => {});
      console.log("Barcode Finished");
    })
    .then(() => {
      const doc = new PDFDocument({ autoFirstPage: false });
      doc.pipe(fs.createWriteStream("./pdfs/customer/" + id + ".pdf"));
      doc.addPage({ size: "A5", margin: 20 });
      doc.lineWidth(1);
      doc.lineCap("butt").moveTo(20, 20).lineTo(399.53, 20).stroke();
      doc.lineCap("butt").moveTo(20, 20).lineTo(20, 575.28).stroke();
      doc.lineCap("butt").moveTo(399.53, 20).lineTo(399.53, 575.28).stroke();
      doc.lineCap("butt").moveTo(20, 575.28).lineTo(399.53, 575.28).stroke();
      doc.fontSize(12).text("Customer Invoice", 40, 40);
      doc.image("./barcodes/" + id + ".png", 40, 40);
      doc.end();
    });
}

解决方案

方案1:直接使用Buffer插入PDF(推荐)

bwip-js返回的PNG Buffer可直接传给pdfkit的doc.image(),无需写入本地文件,既避免异步问题,又减少IO操作:

const PDFDocument = require("pdfkit");
const bwipjs = require("bwip-js");
const fs = require("fs");

function generateCustomerInvoice(data) {
  const id = "12345678"
  bwipjs
    .toBuffer({
      bcid: "code128",
      text: id,
      scale: 3,
      height: 10,
      includetext: true,
      textxalign: "center",
    })
    .then((pngBuffer) => {
      const doc = new PDFDocument({ autoFirstPage: false });
      doc.pipe(fs.createWriteStream("./pdfs/customer/" + id + ".pdf"));
      doc.addPage({ size: "A5", margin: 20 });
      // 绘制边框
      doc.lineWidth(1);
      doc.lineCap("butt").moveTo(20, 20).lineTo(399.53, 20).stroke();
      doc.lineCap("butt").moveTo(20, 20).lineTo(20, 575.28).stroke();
      doc.lineCap("butt").moveTo(399.53, 20).lineTo(399.53, 575.28).stroke();
      doc.lineCap("butt").moveTo(20, 575.28).lineTo(399.53, 575.28).stroke();
      // 添加文本和条形码
      doc.fontSize(12).text("Customer Invoice", 40, 40);
      // 直接传入Buffer,指定格式为png
      doc.image(pngBuffer, 40, 60, { format: "png" });
      doc.end();
      console.log("PDF生成完成");
    })
    .catch(err => {
      console.error("生成失败:", err);
    });
}

方案2:修复异步文件写入的时序问题

如果必须保存本地文件,需要确保文件完全写入后再读取。使用fs.promises.writeFile替代回调版本,保证异步流程顺序:

const PDFDocument = require("pdfkit");
const bwipjs = require("bwip-js");
const fs = require("fs").promises;
const fsSync = require("fs"); // 用于创建写入流

function generateCustomerInvoice(data) {
  const id = "12345678"
  const barcodePath = "./barcodes/" + id + ".png";
  bwipjs
    .toBuffer({
      bcid: "code128",
      text: id,
      scale: 3,
      height: 10,
      includetext: true,
      textxalign: "center",
    })
    .then((png) => {
      return fs.writeFile(barcodePath, png); // 返回Promise确保写入完成
    })
    .then(() => {
      console.log("Barcode Finished");
      const doc = new PDFDocument({ autoFirstPage: false });
      doc.pipe(fsSync.createWriteStream("./pdfs/customer/" + id + ".pdf"));
      doc.addPage({ size: "A5", margin: 20 });
      // 绘制边框
      doc.lineWidth(1);
      doc.lineCap("butt").moveTo(20, 20).lineTo(399.53, 20).stroke();
      doc.lineCap("butt").moveTo(20, 20).lineTo(20, 575.28).stroke();
      doc.lineCap("butt").moveTo(399.53, 20).lineTo(399.53, 575.28).stroke();
      doc.lineCap("butt").moveTo(20, 575.28).lineTo(399.53, 575.28).stroke();
      // 添加文本和条形码
      doc.fontSize(12).text("Customer Invoice", 40, 40);
      doc.image(barcodePath, 40, 60);
      doc.end();
    })
    .catch(err => {
      console.error("生成失败:", err);
    });
}

关键说明

  • 方案1中,直接传入Buffer时可以显式指定{ format: "png" },让pdfkit明确识别格式,避免自动检测出错。
  • 原代码的核心问题是异步时序错误:fs.writeFile是异步操作,第二个then在文件还没写完就执行,导致读取到不完整的文件内容,触发格式识别错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:37:33