我从数据库中读取数据,我从中生成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),还可以找出在该页面上呈现的数据并在数据库中回放位置({{1}在示例中)。如果可以发布完整的解决方案,那就太好了。
答案 0 :(得分:6)
正如我在评论中已经提到的那样,通过先创建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
HeaderFooter1
和HeaderFooter2
示例将向您展示它是如何完成的。
答案 1 :(得分:4)
这不是你问的确切问题的答案,所以如果这篇文章没用,我会删除它。
由于文档很大,您可以通过将数据作为LaTeX发布然后通过pdflatex
运行来获得最佳结果。
优点:
缺点:
如果您对此感兴趣,我可以充实细节。