生成PDF的各种方法有哪些?

时间:2010-12-31 13:50:31

标签: pdf-generation scalable

我有一个想法,一个应用程序将采取一些Flash内容,其中包含图形和图像,如各种几何形状和多边形和一些随机图像,并将它们转换为PDF。

此外,由于我设想这个应用程序可以用于我的多个用户,我希望这个过程快速且可扩展。我能想到的一个可能的解决方案是拥有一个小型闪存客户端,能够组装上述图形和图像。生成某种XML,将其发送到运行Java进程的服务器,该进程可以使用iText呈现PDF。

我想知道其他可能的方法或最佳做法是什么。技术不是问题;开源或商业。

我知道图片上传等会占用不同的时间,因此请考虑图片随时可用。以下是我在PDF渲染解决方案中寻找的标准:

  1. 因为PDF渲染引擎而没有Flash客户端的约束。
  2. 可扩展至多个用户
  3. 速度和效率
  4. 最少量的序列化/反序列化
  5. 如果您能分享您的技术堆栈创意,我将不胜感激。非常感谢!

    PS:如果你没有陷入我的Flash>>我会很感激。 XML>> Java方法。 我认为这是可以采取的众多方法之一。

4 个答案:

答案 0 :(得分:3)

如果使用Flash在浏览器中生成PDF是一种选择,那么请考虑使用AlivePdf。如果没有,那么请查看XSL:FO,我们将其用于服务器端转换为PDF。

答案 1 :(得分:1)

我相信iText会在Java代码中生成PDF。它可能会也可能不会使用XML作为其数据源; POJO也会做得很好。

另一种方式是XSL-FO。它需要XML数据源和XSL-FO样式表来转换XML并生成PDF。 Apache的Xalan(或任何其他XSL-T库)可以为您完成。

“快速”和“可扩展”可能需要更多这些。上传大量图像是一个具有自己的时间刻度和优化的过程,与PDF无关。

答案 2 :(得分:1)

pdflib for PHPFPDF(也适用于PHP)。

答案 3 :(得分:0)

所以你也愿意考虑其他客户?听起来你有一个孩子绘制应用程序,并希望生成一些东西,以保持他们当时的绘图状态。

让我们面对现实,XML效率不高。这不是它的目的。它既是机器也是人类可读,可验证等等。

相反,如何基于<Canvas>的网页以JSON的形式将该画布的状态提交给服务器(更少的字节,更少的工作来构建它们)。然后,服务器可以在任何地图库/语言中工作。很多JSON-&gt; my-language库漂浮在那里。

您在PDF库中的选择仅限于您在服务器上安装的内容。你还说你想做尽可能少的阅读/写作。

最有效的设置是将已读的部分PDF已加载到内存中,以最大限度地减少画布更改(包括图像)的影响。每个会话都会欺骗部分PDF,将JSON转换为PDF图形命令,并保存PDF。

要最大限度地减少对PDF的结构更改,您需要使用内嵌图像。 PDF中没有新对象意味着您根本不需要更改交叉引用表(直到您添加字体或想要重用现有图像)。您可以使用对象之间的特定空间填充构建“doc info”字典,这样您就可以在不更改任何字节偏移的情况下填充它(这会强制您重新计算外部参照表)。

您可能需要也可能不需要弄乱页面大小...我们只是在这里讨论一页,对吗?

所以PDF看起来像......

%%PDF-1.6
<3-4 random high order bytes to convince folks that we're a binary stream>
1 0 obj
<</Type/Catalog/Pages 2 0 R>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[3 0 R]>>
endobj
3 0 obj
<</Type/Page/Contents 4 0 R/MediaBox[0 0 612 792]/Parent 2 0 R>>
endobj
5 0 obj
<</Type/DocInfo/Author()  --<insert big whitespace gap here>-- 
/Title() --<ditto>--
/Subject() --<ditto>--
/Keywords() --<ditto>--
/Creator(My app's Name)
/Producer(My pdf library's name)
/CreationDate(encodedDateWhenThisTemplateWasBuilt) D:YYYYMMDDHHMMSS-timeZoneOffset
/ModDate() --<another, smaller whitespace gap>--
>>
4 0 obj
<</Filter/SeveralDifferentFiltersAvailable/Length --<byte length of the stream in this file>-->>
stream

你的模板停在那里。你有一个类似的“PDF结束”模板,看起来像这样:

endstream
endobj
xref
0 6
0000000000 65535 f 
0000000010 00000 n
0000000025 00000 n
0000000039 00000 n
0000000097 00000 n
0000000050 00000 n
trailer
<</Root 1 0 R/Size 6/Info 5 0 R>>
startxref
--<some white space>--
%%EOF

最后的数字列都是错误的。第一列是该特定对象的字节偏移量(我现在还没有计算字节数,谢谢你)。第二栏基本上无关紧要。

PDF填充应用程序需要知道:

  1. 您打算在第一个模板中填写的所有内容的字节偏移量。
    1. 所有“doc info”字段,顺便说一下都是可选的。 / Info键及其指向的字典对于此事是可选的。如果你愿意的话,你可以猛拉它们。
    2. 内容流的/ Length键。这需要是流本身的后过滤器字节长度。
  2. 如何将JSON转换为pdf绘图命令。如果你想作弊,你可以使用iText [Sharp]的PdfContentByte类,使用它的绘图命令,然后获取完成的字节流并将其打入你的PDF。一定要使用内联图像,否则整个方案就会出现在窗外。如果您觉得有必要,可能还有其他类似的图书馆。或者你可以阅读PDF规范并推出自己的规范。您将坚持使用相当有限的PDF内容语法。
  3. 文件开头的单词“xref”的字节偏移量。你可以计算:LengthOfInitialTemplate + LengthOfContentStream + OffsetFromStartOf2ndTemplateTo'xref'。
  4. “startxref”下面一行的字节偏移量,这是您编写上述'xref'字节偏移量的地方
  5. 你不会比那更有效率。你曾经读过你的模板一次。读取/计算一次所需的字节偏移量。