【问题标题】:what are the various approaches for generating PDFs?生成 PDF 的各种方法是什么?
【发布时间】:2010-12-31 13:50:30
【问题描述】:

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

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

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

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

  1. 因为 PDF 渲染引擎,所以对 Flash 客户端没有限制。
  2. 可扩展到多个用户
  3. 速度和效率
  4. 最少的序列化/反序列化

如果您能分享您的技术堆栈想法,我将不胜感激。非常感谢!

PS:如果您不被我的 Flash >> XML >> Java 方法所困扰,我将不胜感激。 我相信这是可以采取的众多方法之一。

【问题讨论】:

    标签: pdf-generation scalable


    【解决方案1】:

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

    【讨论】:

    • 谢谢,但是除了使用 XML 还有其他方法吗?
    • AlivePdf 不需要 XML。
    【解决方案2】:

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

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

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

    【讨论】:

    • 谢谢,我只是根据我在技术堆栈中寻找的标准为问题添加了更多细节。
    【解决方案3】:

    有 pdflib for PHP 和 FPDF(也适用于 PHP)。

    【讨论】:

    • 谢谢。所以我想,使用 FPDF 意味着在 Flash 客户端和 FPDF 之间使用 XML 进行通信?
    • @andthereitgoes:嗯,这些库中的每一个都使用自己的命令,所以是的,您需要将它们序列化为某种东西,可能是 XML,以便从 flash 客户端获取到 FPDF。
    【解决方案4】:

    所以您也愿意考虑其他客户?听起来您有一个儿童绘画应用,并且想要生成一些可以保留他们当时绘画状态的东西。

    让我们面对现实吧,XML 并没有那么高效。这不是它的目的。它是机器和人类可读、可验证等的。

    相反,基于<Canvas> 的网页以 JSON 格式将画布的状态提交给服务器(更少的字节,构建它们的工作量更少)。然后,服务器可以使用它想要的任何地狱库/语言工作。大量的 JSON->my-language 库在那里漂浮。

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

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

    为了尽量减少对 PDF 的结构更改,您需要使用内联图像。 PDF 中没有新对象意味着您根本不需要更改交叉引用表(直到您添加字体或想要重用现有图像)。您可以构建“文档信息”字典,并在对象之间填充特定数量的空格,这样您就可以在不更改任何字节偏移量的情况下填充它(这将迫使您重新计算外部参照表)。

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

    所以 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. 所有“文档信息”字段,顺便说一下,它们都是可选的。 /Info 键和它指向的字典是可选的。如果你愿意,你可以把它们拉下来。
      2. 内容流的 /Length 键。这需要是流本身的过滤后字节长度。
    2. 如何将 JSON 转换为 pdf 绘图命令。如果您想作弊,您可以使用 iText[Sharp] 的 PdfContentByte 类,使用它的绘图命令,然后获取完成的字节流并将其添加到您的 PDF 中。确保您使用内联图像,否则整个方案都会出现在窗外。如果您觉得有需要,可能还有其他类似的库。或者,您可以阅读 PDF 规范并自行编写。您将坚持使用相当有限的 PDF 内容语法子集。
    3. 单词“xref”从文件开头的字节偏移量。您可以这样计算:LengthOfInitialTemplate + LengthOfContentStream + OffsetFromStartOf2ndTemplateTo'xref'。
    4. “startxref”下面的行的字节偏移量,这是您写入“xref”的预先计算的字节偏移量的地方

    您不会比这更有效率。你曾经读过你的模板。读取/计算一次您需要的字节偏移量。

    【讨论】:

      猜你喜欢
      • 2013-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      相关资源
      最近更新 更多