簡體   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