繁体   English   中英

从大量数据生成大PDF

[英]Generate big PDF from huge amount of data

我从数据库中读取数据,从中生成HTML DOM。 数据量巨大,因此它不能同时适应内存,但它可以逐块提供。

我想使用Flying Saucer将生成的HTML转换为PDF:

import org.xhtmlrenderer.pdf.ITextRenderer;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.DOMWriter;

OutputStream bodyStream = outputMessage.getBody();

ITextRenderer renderer = new ITextRenderer();

DocumentFactory documentFactory = DocumentFactory.getInstance();
DOMWriter domWriter = new DOMWriter();

Element htmlNode = documentFactory.createElement("html");
Document htmlDocument = documentFactory.createDocument(htmlNode);

int currentLine = 1;
int currentPage = 1;

try {
    while (currentLine <= numberOfLines) {
        currentLine += loadDataToDOM(documentFactory, htmlNode, currentLine, CHUNK_SIZE);

        renderer.setDocument(domWriter.write(htmlDocument), null);
        renderer.layout();

        if (currentPage == 1) {
            // For the first page the PDF writer is created:
            renderer.createPDF(bodyStream, false);
        }
        else {
            // Other documents are appended to current PDF writer:
            renderer.writeNextDocument(currentPage);
        }

        currentPage += renderer.getRootBox().getLayer().getPages().size();
    }

    // Finalise the PDF:
    renderer.finishPDF();
}
catch (DocumentException e) {
    throw new IOException(e);
}
catch (org.dom4j.DocumentException e) {
    throw new IOException(e);
}
finally {
    IOUtils.closeQuietly(bodyStream);
}

这种方法的问题在于块的最后一页不一定完全填充数据。 有没有解决方案填补这个空间? 例如,我可以考虑一种方法,它将检查最后一页是否未完全归档,然后丢弃它(不写入PDF),还要找出在该页面上呈现的数据并在数据库中currentLine位置(示例中为currentLine ) 。 如果可以发布一个完整的解决方案会很好。

正如我在评论中已经提到的那样,通过先创建HTML然后将HTML转换为PDF,您可以通过从数据源创建PDF来浪费内存和处理时间。 你还引入了许多不必要的复杂性。

在您的评论中,您提到了低级功能,例如moveTo()lineTo() 使用绘制每一行和单个单词的低级操作来绘制表格确实是疯狂的。

您应该使用PdfPTable类。 ArrayToTable示例是一个非常简单的POC,其中数据以List<List<String>>的形式出现。 代码就像这样简单:

PdfPTable table = new PdfPTable(8);
table.setWidthPercentage(100);
List<List<String>> dataset = getData();
for (List<String> record : dataset) {
    for (String field : record) {
        table.addCell(field);
    }
}
document.add(table);

当然:您正在谈论一个庞大的数据集,在这种情况下,您可能不希望先在内存中构建table ,然后在将表添加到文档时刷新内存。 在构建表时,您需要添加表的一小部分。 这就是MemoryTests示例中发生的事情。 添加此行:

table.setComplete(false);

您可以一点一点地添加表格(在示例中:每10行)。 当您完成向表格添加单元格后,您应该这样做:

table.setComplete(true);
document.add(table);

这将添加最后一行。

如果您想要一个包含重复页眉和/或页脚的表,请查看此PDF中的表: header_footer_1.pdf

HeaderFooter1HeaderFooter2示例将向您展示它是如何完成的。

这不是你问的确切问题的答案,所以如果这篇文章没用,我会删除它。

由于文档很大,您可以通过将数据作为LaTeX发布然后通过pdflatex运行来获得最佳结果。

好处:

  • 您需要的LaTeX源很容易发出 - 不比HTML复杂。
  • 整个TeX系统旨在生成美丽而庞大的文档。 LaTeX作为页面流处理。 页数对所需的RAM资源基本没有影响。
  • 您将获得排版语言的全部功能,使您的页面看起来很棒。 想要花哨的标题? 位置很好的页码? 章节标题? 可点击的目录等等没问题。
  • LaTeX适用于所有主要操作系统。

缺点:

  • LaTeX是本机可执行文件,而不是Java库。

如果你对此感兴趣,我可以充实细节。

暂无
暂无

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

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