使用pdfkit在pdf中嵌入javascript

时间:2014-03-11 16:31:51

标签: javascript pdf pdf-generation node-pdfkit

是否可以将一些javascript代码嵌入到我使用NodeJS PDFKit(http://pdfkit.org/)创建的pdf文件中?

我知道如何使用PDFSharp在c#中嵌入javascript,当我查看PDFSharp创建的两个文件时,一个嵌入了javascript,一个没有它们有以下不同之处:

带有javascript的那个包含作为最后一个对象插入的其他对象:

30 0 obj
<<
/S/JavaScript
/JS(this.print\(true\); )
>>
endobj
31 0 obj
<<
/Names[(EmbeddedJS)30 0 R]
>>
endobj

在这种情况下,我嵌入的js是this.print\(true\);。此后,对象引用偏移量也相应地不同。

还有这个:

/Names
<<
/JavaScript 31 0 R
>>

在pdf的第二个对象中引用。整个对象看起来像这样:

2 0 obj
<<
/Type/Catalog
/Pages 3 0 R
/Names
<<
/JavaScript 31 0 R
>>
>>
endobj

当我尝试将此代码插入pdfkit生成的pdf时,我得到一个损坏的文件。有什么我想念的吗?是否有更好的方法可以使用pdfkit将javascript嵌入到pdf中?

PS。当然,我计算正确的物体数量,调整偏移量等。

2 个答案:

答案 0 :(得分:0)

与PDFSharp相比,我看到了更直接的JS嵌入方式: http://bililite.com/blog/2012/06/06/adding-javascript-to-pdf-files/

它看起来像这样:

0 1 obj
<< 
  /Type /Catalog
  /Pages 0 2 R % a standard catalog entry
  /Names << % the Javascript entry
    /JavaScript <<
      /Names [
        (EmbeddedJS)
        <<
          /S /JavaScript
          /JS (
            app.alert('Hello, World!');
          )
        >>
      ]
    >>
  >> % end of the javascript entry
>>
endobj

我继续并采用了骇人听闻的方式作为概念证明:

const originalToString = Object.prototype.toString;
Object.prototype.toString = function() {
  if (this.hasOwnProperty('rawForPdfKit')) {
    return 'hey, pdfkit, this is totally not an object, we pinky promise, please fall back to raw concatenation';
  }
  return originalToString.call(this);
};

function generatePdf() {
  const Raw = (function () {
    function Raw(rawData) {
      this.rawData = rawData;
      this.rawForPdfKit = true;
    }
    Raw.prototype.toString = function () {
      return this.rawData;
    };
    return Raw;
  }());

  const doc = new PdfDocument();
  const raw = new Raw(`<<
    /JavaScript <<
      /Names [
        (EmbeddedJS)
        <<
          /S /JavaScript
          /JS (
            this.print();
          )
        >>
      ]
    >>
  >>`);

  doc['_root'].data.Names = raw;

  ...
}

强制性警告: 此方法依赖于PDFKit的专用API和实现细节,因此,通过PDFKit升级,这可能随时中断任何事情。

答案 1 :(得分:0)

不使用JavaScript即可自动触发打印:

var ref = doc.ref({
  Type: 'Action',
  S: 'Named',
  N: 'Print'
});

doc._root.data.OpenAction = ref;
ref.end();

发件人:https://github.com/foliojs/pdfkit/issues/217#issuecomment-39281561