iTextSharp 比较 2 个 PDF 是否相等

标签 itext

我正在生成 PDF 并将其存储在数据库中。

pdf 数据使用 Convert.ToBase64String(pdf.ByteArray) 存储在文本字段中

如果我生成与数据库中已经存在的完全相同的 PDF,并比较 2 个 base64 字符串,它们是不一样的。很大一部分是相同的,但每次都有大约 5-10% 的文本不同。

如果两个 pdf 使用相同的方法生成,会有什么不同?

这是一个问题,因为我无法判断 PDF 自上次保存到数据库后是否被修改。

编辑:当查看实际pdf时,2个pdf在视觉上看起来完全相同,但字节的base64string不同

最佳答案

两个 看起来 100% 相同的 PDF 在表面上可能完全不同。 PDF 生成程序可以自由地将单词“hello”写成单个单词或以任何顺序写成五个单独的字母。他们还可以自由地先绘制表格的线条,然后再绘制单元格内容,或者先绘制单元格内容,或者这些线条的任意组合,例如一次一个单元格。

如果您实际上是以编程方式创建 PDF,并且您使用完全相同的代码创建了两个 PDF,您仍然不会得到 100% 相同的文件。这有几个原因,最明显的是 PDF 支持创建和修改日期。这些显然会根据创建时间而改变。您可以使用类似这样的方法来覆盖这些(并混淆其他人,所以我不推荐这样做):

var info = writer.Info;
info.Put(PdfName.CREATIONDATE, new PdfDate(new DateTime(2001,01,01)));
info.Put(PdfName.MODDATE, new PdfDate(new DateTime(2001,01,01)));

但是,PDF 还支持预告片的 /ID 条目中的唯一标识符。据我所知,iText 不支持覆盖此参数。您可以复制您的 PDF,手动更改它,然后计算您的差异,您可能会更接近于比较。

然后是字体。在对字体进行子集化时,生产商会根据原始名称和任意选择的六个大写 ASCII 字母创建一个唯一的内部名称。因此,对于字体 Calibri,字体的名称一次可以是 JLXWHD+Calibri,另一次可以是 SDGDJT+Calibri。 iText 不支持覆盖它,因为这样做可能弊大于利。这些内部名称用于避免字体子集冲突。

所以简短的回答是,除非你比较的是两个物理上相互重复的文件,否则你不能对它们的二进制内容进行直接比较。长的答案是你可以调整一些 PDF 条目以删除独特的部分仅用于比较但是你可能需要做更多的工作而不是将文件重新存储在数据库中.

关于iTextSharp 比较 2 个 PDF 是否相等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21990255/

相关文章:

iTextSharp PdfStamper.PartialFormFlattening 仅展平部分而非全部字段

itext - 有表格边框,但没有单元格边框

c# - 使用 ITextSharp 获取 PDF 中图像的位置(X、Y、宽度、高度)

java - iText 在表格中制作一整卷彩色

c# - 在 iTextSharp 中创建混合方向 PDF

java - 用于 html 到 pdf 的 Xmlparser

java - iText - 将内容添加到现有页面的底部

pdf - 获取 itext 7 pdf 文档的自定义元数据

java - iText 中的文本轮廓

java - Android中的Itext段落对齐问题