如何使用Node.js和pdfkit管道传输流

8
在PDFkit 0.5之前,以下内容适用于我(通过pdfkit生成pdf / 通过ipp打印到CUPS):
var ipp = require("ipp");
var PDFDocument = require("pdfkit");

var doc = new PDFDocument;
doc.text("Hello World");

doc.output(function(pdf)){
    var printer = ipp.Printer("http://127.0.0.1:631/printers/1");
    var file = {
        "operation-attributes-tag":{
            "requesting-user-name": "User",
        "job-name": "Print Job",
        "document-format": "application/pdf"
        },
        data: new Buffer(pdf, "binary")
    };

    printer.execute("Print-Job", file, function (err, res) {
        console.log("Printed: "+res.statusCode);
    });
}

从PDFkit 0.5版本开始, output 方法已被弃用 - 但我似乎找不到一个针对我的情况使用新的 pipe 方法的示例。如果我不使用浏览器,是否仍需要像blob-stream这样的模块?

1个回答

19

由于pdfkit PDFDocument现在是流式的,因此您需要缓冲来自缓冲区的数据:

var ipp = require("ipp");
var PDFDocument = require("pdfkit");

var doc = new PDFDocument;
doc.text("Hello World");

var buffers = [];
doc.on('data', buffers.push.bind(buffers));
doc.on('end', function () {
    var printer = ipp.Printer("http://127.0.0.1:631/printers/1");
    var file = {
        "operation-attributes-tag":{
            "requesting-user-name": "User",
        "job-name": "Print Job",
        "document-format": "application/pdf"
        },
        data: Buffer.concat(buffers)
    };

    printer.execute("Print-Job", file, function (err, res) {
        console.log("Printed: "+res.statusCode);
    });
});
doc.end();

您可以使用类似concat-stream模块的东西:
var ipp = require("ipp");
var PDFDocument = require("pdfkit");
var concat = require("concat-stream");

var doc = new PDFDocument;
doc.text("Hello World");

doc.pipe(concat(function (data) {
    var printer = ipp.Printer("http://127.0.0.1:631/printers/1");
    var file = {
        "operation-attributes-tag":{
            "requesting-user-name": "User",
        "job-name": "Print Job",
        "document-format": "application/pdf"
        },
        data: data
    };

    printer.execute("Print-Job", file, function (err, res) {
        console.log("Printed: "+res.statusCode);
    });
}));
doc.end();

运行得非常完美!谢谢! - Josiah
1
这对我也适用。一定要调用doc.end()来实际触发结束事件。我为那些第一次使用该库的人添加了一个修改。 - jeremywoertink
你好!我想在我的代码中使用那个建议。不幸的是,我遇到了一个问题:当我尝试通过 fs.writeFileSync('test.pdf', buffers) 保存二进制数据以便获取其内容时,它生成了一个损坏的文件。@Josiah 有什么建议吗?非常感谢。 - Rogério Oliveira
是的,您可以将缓冲区连接成一个缓冲区,然后再将其传递给fs.writeFileSync:fs.writeFileSync('test.pdf', Buffer.concat(buffers))。当然,为了正确地执行此操作,您应该对其进行流处理,而不需要缓冲:doc.pipe (fs.createWriteStream('test.pdf')) - Farid Nouri Neshat
使用 doc.on('end') 真的很有帮助。我花了4个小时来尝试解决这个问题,而你的解决方案解决了它。这让我不必创建临时文件来上传到其他地方,现在我可以直接发送缓冲区。 - Luke Brown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接