itext 7 html到pdf的转换,并将外部文件链接到生成的pdf

nc1teljy  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(751)

我在合并itext生成的两个pdf时遇到了一个问题。我是itext7的新手,我正在从html创建一个pdf,并用excel(.xls)创建另一个pdf作为嵌入到pdf的文档。我想合并这两个文件。
基本上我想从html生成一个pdf,然后附加一个excel文档到它,然后从这两个pdf输出组合的html输出流。
下面是我正在使用的代码

ByteArrayOutputStream htmlToPdfContent = new ByteArrayOutputStream();
    PdfWriter writer = new PdfWriter(htmlToPdfContent);
    PdfDocument pdf = new PdfDocument(writer);
    pdf.setTagged();
    PageSize pageSize = PageSize.A4.rotate();
    pdf.setDefaultPageSize(pageSize);
    ConverterProperties properties = new ConverterProperties();
    HtmlConverter.convertToPdf(htmlContent, pdf, properties);

    FileUtils.cleanDirectory(new File(outputDir));

    ByteArrayOutputStream pdfResult = new ByteArrayOutputStream();
    PdfWriter writerResult = new PdfWriter(pdfResult);
    PdfDocument pdfDocResult = new PdfDocument(writerResult);

    PdfReader reader = new PdfReader(new ByteArrayInputStream(htmlToPdfContent.toByteArray()));
    PdfDocument pdfDoc = new PdfDocument(reader);
    pdfDoc.copyPagesTo(1, pdfDoc.getNumberOfPages(), pdfDocResult);

    ByteArrayOutputStream pdfAttach = new ByteArrayOutputStream();
    PdfDocument pdfLaunch = new PdfDocument(new PdfWriter(pdfAttach));
    Rectangle rect = new Rectangle(36, 700, 100, 100);
    byte[] embeddedFileContentBytes = Files.readAllBytes(Paths.get(excelPath));
    PdfFileSpec fs = PdfFileSpec.createEmbeddedFileSpec(pdfLaunch, embeddedFileContentBytes, null, "test.xlsx", null, null);
    PdfAnnotation attachment = new PdfFileAttachmentAnnotation(rect, fs)
            .setContents("Click me");
    pdfLaunch.addNewPage().addAnnotation(attachment);

    PdfDocument appliedChanges = new PdfDocument(new PdfReader(new ByteArrayInputStream(pdfAttach.toByteArray())));

    appliedChanges.copyPagesTo(1, appliedChanges.getNumberOfPages(), pdfDocResult);
    try(OutputStream outputStream = new FileOutputStream(dest)) {
        pdfResult.writeTo(outputStream);
    }

这是引发异常

13:56:05.724 [main] ERROR com.itextpdf.kernel.pdf.PdfReader - Error occurred while reading cross reference table. Cross reference table will be rebuilt.
com.itextpdf.io.IOException: Error at file pointer 19,272.
    at com.itextpdf.io.source.PdfTokenizer.throwError(PdfTokenizer.java:678)
    at com.itextpdf.kernel.pdf.PdfReader.readXrefSection(PdfReader.java:801)
    at com.itextpdf.kernel.pdf.PdfReader.readXref(PdfReader.java:774)
    at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:538)
    at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1818)
    at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:238)
    at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:221)
    at com.mediaocean.prisma.order.command.infrastructure.pdf.itext.PdfAttachmentLaunch.main(PdfAttachmentLaunch.java:76)
Caused by: com.itextpdf.io.IOException: xref subsection not found.
    ... 8 common frames omitted
Exception in thread "main" com.itextpdf.kernel.PdfException: Trailer not found.
    at com.itextpdf.kernel.pdf.PdfReader.rebuildXref(PdfReader.java:1064)
    at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:543)
    at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1818)
    at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:238)
    at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:221)
    at com.mediaocean.prisma.order.command.infrastructure.pdf.itext.PdfAttachmentLaunch.main(PdfAttachmentLaunch.java:88)
13:56:05.773 [main] ERROR com.itextpdf.kernel.pdf.PdfReader - Error occurred while reading cross reference table. Cross reference table will be rebuilt.
com.itextpdf.io.IOException: PDF startxref not found.
    at com.itextpdf.io.source.PdfTokenizer.getStartxref(PdfTokenizer.java:262)
    at com.itextpdf.kernel.pdf.PdfReader.readXref(PdfReader.java:753)
    at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:538)
    at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1818)
    at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:238)
    at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:221)
    at com.mediaocean.prisma.order.command.infrastructure.pdf.itext.PdfAttachmentLaunch.main(PdfAttachmentLaunch.java:88)

请告知。提前谢谢!!

ijnw1ujt

ijnw1ujt1#

关于你问题的第二次修改

您更改的代码与我在对问题的第一次修订的回答中建议的不同,您现在将转换为以前未使用的代码 PdfDocument pdf 而不是直接进入 ByteArrayOutputStream htmlToPdfContent .
事实上,这也是一个可能的解决问题中确定的答案。因此,这里不再有例外:

PdfReader reader = new PdfReader(new ByteArrayInputStream(htmlToPdfContent.toByteArray()));
PdfDocument pdfDoc = new PdfDocument(reader);

相反,您现在会得到一个更进一步的异常,如下所示:

PdfDocument appliedChanges = new PdfDocument(new PdfReader(new ByteArrayInputStream(pdfAttach.toByteArray())));

原因很简单,你还没有关闭 PdfDocument pdfLaunch 写在 ByteArrayOutputStream pdfAttach . 但只有关闭才能完成输出流中的pdf。因此,添加 close() :

ByteArrayOutputStream pdfAttach = new ByteArrayOutputStream();
PdfDocument pdfLaunch = new PdfDocument(new PdfWriter(pdfAttach));
[...]
pdfLaunch.addNewPage().addAnnotation(attachment);
pdfLaunch.close(); //<==== added

PdfDocument appliedChanges = new PdfDocument(new PdfReader(new ByteArrayInputStream(pdfAttach.toByteArray())));

你实际上又犯了同样的错误,不久之后,你存储了 ByteArrayOutputStream pdfResultoutputStream 不关闭 PdfDocument pdfDocResult 其中写入 pdfResult . 因此,还要添加 close 在那里打电话:

appliedChanges.copyPagesTo(1, appliedChanges.getNumberOfPages(), pdfDocResult);
pdfDocResult.close(); //<==== added
try(OutputStream outputStream = new FileOutputStream(dest)) {
    pdfResult.writeTo(outputStream);
}

关于你问题的第1次修订

你使用 ByteArrayOutputStream htmlToPdfContent 作为两个不同pdf生成器的目标 PdfDocument pdf 通过 PdfWriter writer 以及 HtmlConverter.convertToPdf 电话:

ByteArrayOutputStream htmlToPdfContent = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(htmlToPdfContent);
PdfDocument pdf = new PdfDocument(writer);
pdf.setTagged();
PageSize pageSize = PageSize.A4.rotate();
pdf.setDefaultPageSize(pageSize);
ConverterProperties properties = new ConverterProperties();
HtmlConverter.convertToPdf(content, htmlToPdfContent, properties);

这使得 htmlToPdfContent 两者输出的大杂烩,尤其不是有效的pdf。
因为你没有添加任何内容到 pdf ,您可以安全地将其删除,并将上述摘录减少到

ByteArrayOutputStream htmlToPdfContent = new ByteArrayOutputStream();
ConverterProperties properties = new ConverterProperties();
HtmlConverter.convertToPdf(content, htmlToPdfContent, properties);

相关问题