【问题标题】:Issue merging PDFs on iText7在 iText7 上合并 PDF
【发布时间】:2022-01-12 20:23:59
【问题描述】:

我有以下方法可以合并我的 PDF 文档。但是,在文档有水印的某些情况下,该方法会引发错误。

public void doMergeUsingItext7(List<InputStream> list, OutputStream outputStream) throws SSException {
    try (com.itextpdf.kernel.pdf.PdfWriter writer = new com.itextpdf.kernel.pdf.PdfWriter(outputStream);) {
        writer.setSmartMode(Boolean.TRUE);
        try (com.itextpdf.kernel.pdf.PdfDocument pdfDoc = new com.itextpdf.kernel.pdf.PdfDocument(writer)) {
            pdfDoc.initializeOutlines();
            list.forEach((in) -> {
                try (com.itextpdf.kernel.pdf.PdfReader reader = new com.itextpdf.kernel.pdf.PdfReader(in);) {
                    reader.setUnethicalReading(Boolean.TRUE);
                    try (com.itextpdf.kernel.pdf.PdfDocument addedDoc = new com.itextpdf.kernel.pdf.PdfDocument(reader)) { //ERROR IS THROWN ON THIS LINE
                        addedDoc.copyPagesTo(1, addedDoc.getNumberOfPages(), pdfDoc);
                        logger.log(Level.INFO, "Successfully Added the Document to PDF");
                    } catch (Exception e) {
                        ExceptionUtils.printRootCauseStackTrace(e);
                    }
                } catch (IOException ex) {
                    ExceptionUtils.printRootCauseStackTrace(ex);
                } catch (Exception e) {
                    ExceptionUtils.printRootCauseStackTrace(e);
                }
            });
        }
    } catch (Exception ex) {
        throw new SSException(ex, "Print Version Failed");
    }
}

文档有水印时会抛出以下错误...

com.itextpdf.kernel.PdfException: Illegal length value.
at com.itextpdf.kernel.pdf.PdfEncryption.readAndSetCryptoModeForStdHandler(PdfEncryption.java:523)
at com.itextpdf.kernel.pdf.PdfEncryption.<init>(PdfEncryption.java:229)
at com.itextpdf.kernel.pdf.PdfReader.readDecryptObj(PdfReader.java:1251)
at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:685)
at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1871)
at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:252)
at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:234)
at gov.ca.lc.util.PdfUtilFuntions.lambda$doMergeUsingItext7$0(PdfUtilFuntions.java:180)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at gov.ca.lc.util.PdfUtilFuntions.doMergeUsingItext7(PdfUtilFuntions.java:176)

我不确定文档中究竟是什么未能合并。非常感谢任何有关解决此问题的帮助。谢谢。

【问题讨论】:

标签: java pdf itext7


【解决方案1】:

这是 iText 中的一个错误。

相关 PDF 已加密。其加密字典的 V 值为 1(“RC4 或 AES 算法,加密密钥长度为 40 位”)和 R 值为 3(“对于加密的文件V 值为 2 或 3,或任何“修订版 3 或更高版本的安全处理程序”访问权限设置为 0")。

密钥长度的 Length 值仅针对 V 2 或 3 指定,对于 V 1,密钥长度固定为 40 . 尽管如此,iText 在 R 3 的情况下需要 Length 值。

由于文档的加密字典中没有 Length 值,iText 无法读取该文件。


附带说明:如今 40 位密钥长度的安全性是没有安全性的。所以很可能这个问题没有更早出现,因为使用 V 1 安全性(或一般的 40 位密钥长度安全性)是无用的,因此没有认真对待任何用例。


快速修复

如果您不回避重新编译 iText,修复错误很容易。只需编辑 iText 内核类com.itextpdf.kernel.pdf.PdfEncryption。它的方法readAndSetCryptoModeForStdHandler

开头
int cryptoMode;
int length = 0;

PdfNumber rValue = encDict.getAsNumber(PdfName.R);
if (rValue == null)
    throw new PdfException(KernelExceptionMessageConstant.ILLEGAL_R_VALUE);
int revision  = rValue.intValue();
boolean embeddedFilesOnlyMode = readEmbeddedFilesOnlyFromEncryptDictionary(encDict);
switch (revision) {
    case 2:
        cryptoMode = EncryptionConstants.STANDARD_ENCRYPTION_40;
        break;
    case 3:
        PdfNumber lengthValue = encDict.getAsNumber(PdfName.Length);
        if (lengthValue == null)
            throw new PdfException(KernelExceptionMessageConstant.ILLEGAL_LENGTH_VALUE);
        length = lengthValue.intValue();
        if (length > 128 || length < 40 || length % 8 != 0)
            throw new PdfException(KernelExceptionMessageConstant.ILLEGAL_LENGTH_VALUE);
        cryptoMode = EncryptionConstants.STANDARD_ENCRYPTION_128;
        break;

这里简单替换

if (lengthValue == null)
    throw new PdfException(KernelExceptionMessageConstant.ILLEGAL_LENGTH_VALUE);
length = lengthValue.intValue();

通过

length = 40;
if (lengthValue != null)
    length = lengthValue.intValue();

(我使用了相同数量的行替换,以便更容易解释后面的堆栈跟踪。)

【讨论】:

  • 感谢您的回复!有什么办法可以绕过这个问题吗?不幸的是,我无法控制最终用户上传的文档。他们所关心的是能够在桌面上打开文档。
  • 你可以给 iText 打补丁吗?
  • 我想应该没问题!除非存在重大漏洞,否则我们不会经常升级库。
  • @SirishV 查看我的答案的编辑,“快速修复”部分解释了要更改的内容
猜你喜欢
  • 1970-01-01
  • 2019-11-17
  • 2017-03-28
  • 2020-10-19
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 2023-01-19
相关资源
最近更新 更多