简体   繁体   English

iText 7 Html 到 Pdf 转换并将外部文件链接到生成的 pdf

[英]iText 7 Html to Pdf conversion and linking external file to the generated pdf

I am encountering an issue while merging two PDFs generated out of IText. I am new to iText7 I am creating one pdf from html and creating another pdf with excel(.xls) as embedded document to pdf. I want to merge the 2 files.我在合并从 IText 生成的两个 PDF 时遇到问题。我是 iText7 的新手,我正在从 html 创建一个 pdf,并使用 excel(.xls) 作为嵌入文档创建另一个 pdf 到 pdf。我想合并这两个文件。

Basically I want to generate a PDF from html then attach a excel document to it and then output combined html outPutStream from these two pdfs.基本上我想从 html 生成一个 PDF 然后附加一个 excel 文档然后 output 从这两个 pdf 组合 html outPutStream。

Below is the code I am using下面是我正在使用的代码

    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);
    }

This is throwing exception这是抛出异常

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)

Please advise.请指教。 Thanks in advance !!提前致谢 !!

Concerning revision 2 of your question关于你的问题的修订 2

You changed your code differently than proposed in my answer to the first revision of your question, you now convert into the formerly unused PdfDocument pdf instead of directly into the ByteArrayOutputStream htmlToPdfContent .您更改的代码与我对您的问题的第一次修订的回答中建议的不同,您现在转换为以前未使用的PdfDocument pdf而不是直接转换为ByteArrayOutputStream htmlToPdfContent

This actually also is a possible fix of the problem identified in that answer.这实际上也是该答案中确定的问题的可能解决方案。 Thus, you don't get an exception here anymore:因此,您不再在这里遇到异常:

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

Instead you now get an exception further down the flow, here:取而代之的是,您现在在流程的后面得到一个异常,在这里:

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

And the reason is simple, you have not yet closed the PdfDocument pdfLaunch which writes to the ByteArrayOutputStream pdfAttach .原因很简单,您尚未关闭写入ByteArrayOutputStream pdfAttach PdfDocument pdfLaunch But only closing finalizes the PDF in the output stream. Thus, add the close() :但只有关闭才能最终确定 output stream 中的 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())));

And you actually do the same mistake again, shortly after, you store the contents of the ByteArrayOutputStream pdfResult to outputStream without closing the PdfDocument pdfDocResult which writes to pdfResult .你实际上又犯了同样的错误,不久之后,你将ByteArrayOutputStream pdfResult的内容存储到outputStream而没有关闭写入 pdfResult 的PdfDocument pdfDocResult pdfResult Thus, also add a close call there:因此,还要在那里添加一个close调用:

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

Concerning revision 1 of your question关于你的问题的修订 1

You use the ByteArrayOutputStream htmlToPdfContent as target of two distinct PDF generators, the PdfDocument pdf via the PdfWriter writer and the HtmlConverter.convertToPdf call:您使用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);

This makes the content of htmlToPdfContent a hodgepodge of the outputs of both of them, in particular not a valid PDF.这使得htmlToPdfContent的内容成为两者输出的大杂烩,特别是不是有效的 PDF。

As you don't add any content to pdf , you can safely remove it and reduce the above excerpt to由于您没有向pdf添加任何内容,您可以安全地删除它并将上面的摘录减少到

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM