首页 > 解决方案 > 为什么 nodeJs 不从磁盘读取整个二进制文件?

问题描述

我有一个 PDF 文件,我想使用 NodeJS 将其读入内存。理想情况下,我想对其进行编码以base64用于传输它。但不知何故,该read功能似乎没有读取完整的 PDF 文件,这对我来说毫无意义。原始 PDF 是使用 生成的pdfKit,并且可以使用 PDF 阅读器程序查看。

原始文件test.pdf在磁盘上有 90kB。但是,如果我将其读取并写入磁盘,则只有 82kB 并且新的 PDFtest-out.pdf不正常。pdf查看器说:

无法打开文档。pdf 文档已损坏。

因此,base64 编码也无法正常工作。我使用这个webservice对其进行了测试。有人知道为什么以及这里发生了什么吗?以及如何解决。

我已经找到了这个帖子。

fs = require('fs');
let buf = fs.readFileSync('test.pdf'); // returns raw buffer binary data
// buf = fs.readFileSync('test.pdf', {encoding:'base64'}); // for the base64 encoded data
// ...transfer the base64 data...
fs.writeFileSync('test-out.pdf', buf); // should be pdf again

编辑 MCVE:

const fs = require('fs');
const PDFDocument = require('pdfkit');

let filepath = 'output.pdf';

class PDF {
  constructor() {
    this.doc = new PDFDocument();
    this.setupdocument();
    this.doc.pipe(fs.createWriteStream(filepath));
  }

  setupdocument() {
    var pageNumber = 1;
    this.doc.on('pageAdded', () => {
        this.doc.text(++pageNumber, 0.5 * (this.doc.page.width - 100), 40, {width: 100, align: 'center'});
      }
    );

    this.doc.moveDown();
    // draw some headline text
    this.doc.fontSize(25).text('Some Headline');
    this.doc.fontSize(15).text('Generated: ' + new Date().toUTCString());
    this.doc.moveDown();
    this.doc.font('Times-Roman', 11);
  }

  report(object) {

    this.doc.moveDown();
    this.doc
      .text(object.location+' '+object.table+' '+Date.now())
      .font('Times-Roman', 11)
      .moveDown()
      .text(object.name)
      .font('Times-Roman', 11);

    this.doc.end();
    let report = fs.readFileSync(filepath);
    return report;
  }
}

let pdf = new PDF();
let buf = pdf.report({location: 'athome', table:'wood', name:'Bob'});
fs.writeFileSync('outfile1.pdf', buf);

标签: javascriptnode.jspdffile-ionode-pdfkit

解决方案


encoding选项fs.readFileSync()是让您告诉readFile函数文件已经是什么编码,以便读取文件的代码知道如何解释它读取的数据。它不会将其转换为该编码。

在这种情况下,您的 PDF 是二进制的 - 并不是base64您告诉它尝试将其转换base64为二进制,这会导致它弄乱数据。

您根本不应该传递该encoding选项,然后您将获得 RAW 二进制缓冲区(这是 PDF 文件的内容 - 原始二进制文件)。如果您出于某种原因想要将其转换为 base64,则可以buf.toString('base64')对其进行操作。但是,这不是它的原生格式,如果您将转换后的数据写回磁盘,它就不是合法的 PDF 文件。

要仅将同一文件读取和写入到不同的文件名,请完全取消编码选项:

const fs = require('fs');
let buf = fs.readFileSync('test.pdf'); // get raw buffer binary data
fs.writeFileSync('test-out.pdf', buf); // write out raw buffer binary data

推荐阅读