Node.js PNG 缓冲区出现未知图像格式错误

问题描述 投票:0回答:1

我正在使用 bwip-js 生成条形码,并使用 pdfkit 生成将显示所述条形码的 pdf。

我让 bwip-js 生成条形码的 png 图像,但它只提供 png 的缓冲区。然后我使用 fs.writeFile 从该缓冲区生成一个 png(这部分可能做错了)。

无论如何,当我将 png 放入 pdf 中时,pdfkit 会给出一个错误,指出该图像是

Uknown image format

同时,如果我在计算机的文件资源管理器中打开保存png的目录,我就可以很好地打开图像。

我发现this答案似乎描述了同样的问题,但我没有运气让bwip-js使用.PNG而不是.png生成png

我觉得好像我在这里遗漏了一些东西,因为我获取了 bwip-js 提供的缓冲区并将其转换为 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();
    });
}
node.js pdfkit bwip-js
1个回答
0
投票

你写的“.png”图像部分是错误的。

Node.js 在非阻塞 I/O 模型上运行,这意味着它不会等待读取或写入文件系统等操作完成后再继续执行下一行代码。这对于性能来说非常有用,但当一项操作依赖于另一项操作的完成时可能会导致问题。

在您的函数中,您使用 fs.writeFile() 将条形码图像写入磁盘。此方法是异步的 – 它启动写入过程,然后立即继续,而不等待文件写入完成。

fs.writeFile() 函数是异步的。

这意味着它启动文件写入过程,然后立即进入下一行代码,而不等待文件写入完成。

所以下一步“fs.createWriteStream()”没有机会读取完成的图像。 所以这段代码将创建正确的 PDF 文件。

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

function generateCustomerInvoice(invoiceData) {
    const id = invoiceData.invoiceNumber;
    const barcodeDir = "./barcodes/";
    const pdfDir = "./pdfs/customer/";

    if (!fs.existsSync(barcodeDir)) {
        fs.mkdirSync(barcodeDir, { recursive: true });
    }

    if (!fs.existsSync(pdfDir)) {
        fs.mkdirSync(pdfDir, { recursive: true });
    }

    bwipjs.toBuffer({
        bcid: "code128",
        text: id,
        scale: 3,
        height: 10,
        includetext: true,
        textxalign: "center",
    })
        .then((png) => {
            return new Promise((resolve, reject) => {
                fs.writeFile("./barcodes/" + id + ".png", png, (err) => {
                    if (err) {
                        console.error("Error writing file:", err);
                        reject(err);
                    } else {
                        console.log("Barcode Finished");
                        resolve();
                    }
                });
            });
        })
        .then(() => {
            const doc = new PDFDocument({ autoFirstPage: false });
            doc.pipe(fs.createWriteStream("./pdfs/customer/" + id + ".pdf"));
            doc.addPage({ size: "A5", margin: 20 });

            doc.fontSize(12).text("Customer Invoice", 40, 30);

            doc.image("./barcodes/" + id + ".png", 40, 60, { width: 150 });

            doc.fontSize(10).text(`Customer Name: ${invoiceData.customerName}`, 40, 130);

            const tableTop = 160;
            doc.fontSize(10);
            doc.text("Description", 40, tableTop);
            doc.text("Quantity", 200, tableTop);
            doc.text("Price", 280, tableTop);
            doc.text("Total", 360, tableTop);

            let verticalPosition = tableTop;
            invoiceData.items.forEach(item => {
                verticalPosition += 20;
                doc.text(item.description, 40, verticalPosition);
                doc.text(item.quantity, 200, verticalPosition);
                doc.text(`$${item.price.toFixed(2)}`, 280, verticalPosition);
                doc.text(`$${(item.quantity * item.price).toFixed(2)}`, 360, verticalPosition);
            });

            doc.end();
        })
        .catch((err) => {
            console.error("Error in PDF generation: ", err);
        });
}

generateCustomerInvoice({
    customerName: "Tom Cruise",
    invoiceNumber: "INV-10001",
    items: [
        { description: "Item 1", quantity: 2, price: 100.00 },
        { description: "Item 2", quantity: 5, price: 50.00 }
    ],
});

结果

更多详情请参见这里

© www.soinside.com 2019 - 2024. All rights reserved.