使用iText

时间:2018-09-17 17:56:18

标签: pdf itext

免责声明:

我正在使用iText5。我知道这通常是不容易的(与使用iText 7相比),但是我正在使用大量使用iText 5的旧代码,并且升级不受我的控制。

要求:

  • 接收到一个“简单的” PDF / A作为输入(仅文本,它们是从RTF生成的),以及对应于所需的第一页长度(以英寸为单位)的浮点值。
  • 必须输出与输入PDF相同的PDF / A,但分页如下:第一页长度=输入值;每个后续页面(不是第一页或最后一页)都将填充标准页面长度;最后一页将在最接近页面底部的内容下方被截断恒定数量的点。请注意,输入和输出宽度将相同且恒定。

进度/方法:

我扩展了SimpleTextExtractionStrategy来生成XML,其中包含字体信息(大小和字体,粗体或斜体等)以及位置信息(相对于绝对坐标系,其原点位于左上角)从输入PDF提取的每个“跨度”文本的输入)。

然后我逐页生成一个新的PDF(根据上述要求,每个页面都是所需的长度),基于每个新页面的边界使用LINQ过滤提取的XML信息,并在处添加适当格式的文本使用ColumnText.ShowTextAligned(...)的适当位置。

问题:

上面概述的方法很好。它生成具有所需页面结构的PDF,但是在翻译中会丢失一些信息,即彩色文本和带下划线的文本。虽然这些PDF中不应显示彩色文本,但绝对必须检测到带下划线的文本。

这组要求还应包括带有表格的PDF。我最初计划实现一个与表PDF保持相同接口的不同模块,因为它们是与RTF生成的PDF分别生成和使用的,并且iText具有内置的相对强大的表功能。

上面概述的两个问题,再加上我所描述的方法源于重用现有代码的尝试,使我相信完全不同的方法可能是必要的,或者至少要好得多。在我看来,应该有一种方法来捕获内容字节信息并根据需要进行裁剪,以“重新分页”输入的PDF,仅担心移动沿页面边界的内容。

本质上,我正在寻找(基于iText的)建议以寻求更好的方法。伪代码类型的答案或仅对可能有所帮助的类/接口的建议是可以接受的。虽然将文本和表格一起处理将是不错的选择,但也可以理解与其中一个或另一个有关的任何建议。我仔细阅读了iText网站上的许多可用文档以及其他有关SO的问题,但没有找到我想要的东西。

请注意,此问题不包含任何代码,因为我正在寻找一种与我尝试过的完全不同的高级方法。

编辑:

我以前没有注意到它,但是我重用字体(类似于this)的方式导致了一些意想不到的(但有据可查)行为。看来我将需要避免在文本级别上提取信息以进行重新分页,因为很难确保输入和输出之间字体的连续性。

1 个答案:

答案 0 :(得分:0)

不久前我解决了这个问题,但认为我会发布解决方案。我确定这不是最有效的解决方案,但对于我的目的来说效果很好。请注意,这将按照包含仅文本的问题中的说明重新分页PDF。表格PDF单独处理。

基本过程是这样的:

  1. 使用自定义TextExtractionStrategy来提取XML,其中包含有关输入PDF中所有文本的上升和下降行以及其最初显示在哪个页面上的信息。
  2. 鉴于问题中所述的页面长度要求(第一页=输入值,后续=标准长度,最后一页=适合内容)和有关文本位置的XML信息,确定哪些内容适合输出的每一页PDF。创建一个地图,该地图将需要裁剪每个输入页面的位置(顶部和底部,请注意,每个输入页面可能会被裁剪多次),以及一个地图,其中裁剪的页面将需要在页面中一起“连接”最终输出。
  3. 将输入的PDF逐页复制到中间临时PDF(使用PdfCopier)。如果输入页面必须裁切一次以上(例如:输入页面1的前2英寸=页面1输出,输入页面1的下6英寸=页面2输出,输入页面1的最后0.5英寸=页面3输出的顶部) ),请确保将其复制适当的次数(每作物1次)。
  4. 适当裁剪中间复制的PDF的每一页。这可以通过修改MediaBox和/或CropBox来完成。
  5. 将适当的裁剪页面连接到最终输出PDF的页面中。我用PdfWriter首先创建了一个适当高度的新页面,然后使用contentByte.AddTemplate(inputCroppedPage, 0, bottomOfLastAddedCroppedPage)在输出PDF页面的字节内容中的适当位置添加了每个适当的裁剪页面。

对所有设法阅读并理解所有内容的人表示祝贺。对于其他任何人,如果您感到困惑,请告诉我。上面描述的解决方案有点扭曲,很难说出来。尽管此处有太多代码可发布(并且我无权在GitHub或类似代码上共享代码),但我很乐意回答任何有助于他人实现类似功能的问题。

第1步中提到的TextExtractionStrategythis answer的启发。本质上,我使用System.Xml.Linq来创建XML文档,而不是使用字符串来形成HTML,并且我忽略了所有字体信息,只存储了有关文本在页面中位置的信息(您将看到此信息可用)。在链接的答案中,只是没有写到最终的HTML中。)