转换 java 中的 PDF 文件版本(不仅是 header 版本!)

Convert PDF file version in java (not only header version!)

我正在尝试将 PDF 1.3 版转换为 PDF 1.5 版或更高版本。这里的挑战是:我不想像几乎所有的论坛一样只更改 header 版本。我想更改所有文件版本。

我读了这个主题:convert PDF to an older version from a servlet?,但首先新版本的 iTextPdf 7 不支持 PdfStamper,所以我就跳过它。

我想我需要创建一个 TMP 文件,将 PDF 写入 TMP,用 TMP 替换原始文件并删除 TMP。但是我怎样才能在 JAVA 中做到这一点?

此代码只转换HEADER版本!我使用 Itext 版本 7.

WriterProperties wp = new WriterProperties();

wp.setPdfVersion(PdfVersion.PDF_1_7);

PdfDocument pdfDoc = new PdfDocument(new PdfReader("source"), new PdfWriter("destination", wp));

pdfDoc.close();

有什么建议吗?

图片来自 Firefox (PDF v 1.3) picture: no text available

您可以在此处下载 pdf 示例:https://wetransfer.com/downloads/ce2d2f41ac29c36baa2ac895ebc0473c20210922065257/5889b2

无需将 PDF 1.3 版转换为 PDF 1.5 版或更高版本,因为 PDF 设计为向后兼容。这样,每个 PDF 1.3 文件既是一个 PDF 1.4 文件。和一个 PDF 1.5 文件。和一个 PDF 1.6 文件。 ...

您在评论中解释了为什么仍要更改版本:

But if you want to open PDF 1.3 in Firefox, you cannot open it! So we have some clients which use firefox for opening PDF formats. Firefox only support 1.5 and above

鉴于上面讨论的兼容性,这没有意义。但有时程序会以一种荒谬的方式运行。因此,我测试了这个。

结果:我在此处安装的 Firefox 87.0 接受我在文档中找到的 PDF 1.3 和 PDF 1.4 文件,没有任何问题!

很遗憾,我这里没有任何 PDF 1.2(或更早版本)文件,因此我无法检查是否支持此类文件。

所以,恐怕你得回过头来分析你的客户遇到的问题,这不是“Firefox 只支持 1.5 及更高版本”那么简单。

(一些想法:也许您的 PDF 1.3 文件实际上已损坏,因此 Firefox 无法打开它们;它们可能已经在您这边损坏了,或者它们可能在传输给您的客户的过程中损坏了。或者也许是您的客户某些较旧的 Firefox 版本在其 PDF 查看器中存在一些错误。)

针对实际问题的修复

OP 在这里的评论中提供了示例文件。分析它们发现实际问题是 Firefox 无法正确确定嵌入字体的内置编码。

为了在这方面帮助 Firefox,我们可以提供一个显式的基本编码,因此 Firefox 不需要内置编码。

当您在问题中使用 iText 7 时,这里有一个使用示例 PDF 的概念验证:

try (   PdfReader pdfReader = new PdfReader("1100-SD-9000455596.pdf");
        PdfWriter pdfWriter = new PdfWriter("1100-SD-9000455596-Fixed.pdf");
        PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) ) {
    for (int page = 1; page <= pdfDocument.getNumberOfPages(); page++) {
        PdfPage pdfPage = pdfDocument.getPage(page);
        PdfResources pdfResources = pdfPage.getResources();
        for (Entry<PdfName, PdfObject> fontEntry : pdfResources.getResource(PdfName.Font).entrySet()) {
            PdfObject fontObject = fontEntry.getValue();
            if (fontObject != null && fontObject.getType() == PdfObject.INDIRECT_REFERENCE) {
                fontObject = ((PdfIndirectReference)fontObject).getRefersTo(true);
            }
            if (fontObject instanceof PdfDictionary) {
                PdfDictionary fontDictionary = (PdfDictionary) fontObject;
                PdfDictionary encodingDictionary = fontDictionary.getAsDictionary(PdfName.Encoding);
                if (encodingDictionary != null) {
                    if (encodingDictionary.getAsName(PdfName.BaseEncoding) == null &&
                            encodingDictionary.getAsArray(PdfName.Differences) != null) {
                        encodingDictionary.put(PdfName.BaseEncoding, PdfName.WinAnsiEncoding);
                    }
                }
            }
        }
    }
}

(FixForFirefox 测试 testFix1100_SD_9000455596)