iText 如何同时使用 PdfWriterPipeline 和 PdfSmartCopy?

iText how to use PdfWriterPipeline and PdfSmartCopy at the same time?

我正在使用 iText 将 HTML 转换为 PDF 文件。我意识到输出文件太大,所以我决定使用 PdfSmartCopy 来删除对象重复。我可以在 HTML-to-PDF 过程完成后使用 PdfSmartCopy,例如,我使用 PdfSmartCopy 从磁盘加载文件并将 PDF 转换为更小的尺寸。

我的问题是,我可以简化 PdfSmartCopy 和 HTML 到 PDF 的过程吗?我发现 PdfSmartCopyPdfWriter 的子类。所以我将代码更改为:

public static void main(String[] args) throws Exception {
    try (OutputStream file = new FileOutputStream(new File("output.pdf"))) {

        Document document = new Document(PageSize.A4);

        //PdfWriter writer = PdfWriter.getInstance(document, file); // remove this line 
        PdfSmartCopy pdfCopy = new PdfSmartCopy(document, file); // change to this line
        pdfCopy.setInitialLeading(12.5f);

        document.open();

        CSSResolver cssResolver = new StyleAttrCSSResolver();
        CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream("itext2\css\bootstrap.min.css"));
        cssResolver.addCss(cssFile);

        HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

        PdfWriterPipeline pdf = new PdfWriterPipeline(document, pdfCopy);
        HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
        CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

        XMLWorker worker = new XMLWorker(css, true);
        XMLParser p = new XMLParser(worker);

        String fileContent = PdfTest.readFile("itext2\template.html");

        p.parse(new StringReader(fileContent));

        document.close();
        pdfCopy.close();
        file.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

不幸的是,我收到以下错误:

ExceptionConverter: java.io.IOException: The document has no pages.
    at com.itextpdf.text.pdf.PdfPages.writePageTree(PdfPages.java:113)
    at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1257)
    at com.itextpdf.text.pdf.PdfCopy.close(PdfCopy.java:1698)
    at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:895)
    at com.itextpdf.text.Document.close(Document.java:416)
    at pdftest.CompressPdfTest.main(CompressPdfTest.java:65)

是否可以在进行 HTML 到 PDF 渲染的同时使用 PdfSmartCopy

https://api.itextpdf.com/iText5/5.5.9/com/itextpdf/text/pdf/PdfSmartCopy.html#PdfSmartCopy-com.itextpdf.text.Document-java.io.OutputStream-

基于@mkl的想法,在HTML-to-PDF渲染的时候,我把它存入了内存,后面用PdfSmartCopy生成slim pdf版本,这样可以防止我生成文件系统中有两个不同的pdf文件(后来很难删除非slim的),如果对其他人有帮助,请粘贴下面的代码:

try (ByteArrayOutputStream byteData = new ByteArrayOutputStream()) {

    Document document = new Document(PageSize.A4);

    PdfWriter writer = PdfWriter.getInstance(document, byteData);           
    writer.setInitialLeading(12.5f);

    document.open();

    CSSResolver cssResolver = new StyleAttrCSSResolver();
    CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream("itext2\css\bootstrap.min.css"));
    cssResolver.addCss(cssFile);

    HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);

    String fileContent = PdfTest.readFile("itext2\template.html");

    p.parse(new StringReader(fileContent));

    document.close();

    PdfReader reader = new PdfReader(byteData.toByteArray());
    Document document1 = new Document();
    File resultFile = new File("result.pdf");
    PdfSmartCopy pdfCopy = new PdfSmartCopy(document1, new FileOutputStream(resultFile));
    document1.open();
    PdfImportedPage page;
    for (int pageNumber = 1; pageNumber <= reader.getNumberOfPages(); pageNumber++) {
        page = pdfCopy.getImportedPage(reader, pageNumber);
        pdfCopy.addPage(page);
    }

    document1.close();
    byteData.close();
} catch (Exception e) {
    e.printStackTrace();
}