java - iText pdf具有相同内容的多个页面

标签 java pdf itext

如何生成每个页面上具有相同内容的多个页面的 pdf 报告。以下是单页报告的代码。多个页面应该在一个 pdf 文件中。

<%
    response.setContentType( "application/pdf" );
    response.setHeader ("Content-Disposition","attachment;filename=TEST1.pdf");

    Document document=new Document(PageSize.A4,25,25,35,0);
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    PdfWriter writer=PdfWriter.getInstance( document, buffer);
    document.open();
    Font fontnormalbold = FontFactory.getFont("Arial", 10, Font.BOLD);
    Paragraph p1=new Paragraph("",fontnormalbold);
    float[] iwidth = {1f,1f,1f,1f,1f,1f,1f,1f};
    float[] iwidth1 = {1f};

    PdfPTable table1 = new PdfPTable(iwidth); 
    table1.setWidthPercentage(100);
    PdfPCell cell =     new PdfPCell(new Paragraph("Testing Page",fontnormalbold));
    cell.setHorizontalAlignment(1);
    cell.setColspan(8);
    cell.setPadding(5.0f);
    table1.addCell(cell);

    PdfPTable outerTable = new PdfPTable(iwidth1); 
    outerTable.setWidthPercentage(100);

    PdfPCell containerCell = new PdfPCell(); 
    containerCell.addElement(table1); 
    outerTable.addCell(containerCell); 
    p1.add(outerTable);

    document.add(new Paragraph(p1));

    document.close();
    DataOutput output = new DataOutputStream( response.getOutputStream() );
    byte[] bytes = buffer.toByteArray();
    response.setContentLength(bytes.length);
    for( int i = 0; i < bytes.length; i++ ) { output.writeByte( bytes[i] ); }
    response.getOutputStream().flush(); 
    response.getOutputStream().close();
%>

最佳答案

有不同的方法来解决这个问题。并非所有的解决方案都是优雅的。

方法一:多次添加同一张表。

我看到你正在创建一个 PdfPTable名为 outerTable 的对象.我将忽略您对这张表所做的愚蠢事情(例如,为什么要将此表添加到段落中?为什么要将具有 colspan 8 的单个单元格添加到具有 8 列的表中?为什么要将此表嵌套到一个单列的表?所有这些恶作剧都很奇怪),但是有 outertable ,你可以这样做:

for (int i = 0; i < x; i++) {
    document.add(outerTable);
    document.newPage();
}

这将添加表 x次,它将为每个表开始一个新页面。这也是评论中的人建议您的,虽然代码看起来非常优雅,但它并不会产生优雅的 PDF。那就是:如果你是我的雇员,如果你这样做,我会解雇你。

为什么?因为添加表需要 CPU 并且您正在使用 x倍您需要的 CPU。此外,您创建的每个表都会创建新的内容流。将添加相同的内容x次到您的文档。您的 PDF 大约为 x比它应该的大几倍。

为什么这会成为解雇开发人员的理由?因为像这样的应用程序通常存在于云中。在云中,通常需要为 CPU 和带宽付费。编写需要多个 CPU 和带宽的代码的开发人员会导致无法接受的成本。在许多情况下,解雇差劲的开发人员、雇佣稍微贵一点的开发人员并购买稍微贵一点的软件,然后由于在 CPU 和带宽方面更高效的代码,从长远来看可以节省大量资金。 -宽度。

方法二:将表格添加到 PdfTemplate , 重用 PdfTemplate .

请看我对 StackOverflow 问题 How to resize a PdfPTable to fit the page? 的回答

在这个例子中,我创建了一个 PdfPTable命名为 table .我知道我希望 table 有多宽( PageSize.A4.getWidth() ),但我事先不知道它会有多高。所以我锁定了宽度,我添加了我需要添加的单元格,然后我可以像这样计算表格的高度:table.getTotalHeight() .

我创建了一个 PdfTemplate这和 table 一样大:
PdfContentByte canvas = writer.getDirectContent();
PdfTemplate template = canvas.createTemplate(
    table.getTotalWidth(), table.getTotalHeight());

我现在添加 table到这个模板:
table.writeSelectedRows(0, -1, 0, table.getTotalHeight(), template);

我把 tableImage 内目的。这并不意味着我们正在栅格化表格,所有文本和行都保留为 vector 数据。
Image img = Image.getInstance(template);

我缩放 img使其适合我想到的页面大小:
img.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());

现在我将 table 垂直放置在中间。
img.setAbsolutePosition(
    0, (PageSize.A4.getHeight() - table.getTotalHeight()) / 2);

如果您想多次添加表格,您可以这样做:
for (int i = 0; i < x; i++) {
    document.add(img);
    document.newPage();
}

与方法 1 有什么区别?好吧,通过使用 PdfTemplate ,您正在创建一个 Form XObject。表单 XObject 是页面流外部的内容流。一个表单 XObject 在 PDF 文件中只存储一次,并且可以多次重复使用,例如在文档的每一页上。

方法三:创建一个单页的 PDF 文档;多次连接文件

您正在内存中创建 PDF。 PDF 存储在 buffer目的。您可以使用 PdfReader 阅读此 PDF像这样:
PdfReader reader = new PdfReader(buffer.toByteArray());

然后你像这样重用这个内容:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Document doc = new Document();
PdfSmartCopy copy = new PdfSmartCopy(doc, baos);
doc.open();
for (int i = 0; i < x; i++) {
    copy.addDocument(reader);
}
doc.close();
reader.close();

现在您可以发送存储在 baos 中的字节了到OutputStream您的response目的。确保您使用 PdfSmartCopy而不是 PdfCopy . PdfCopy只是按原样复制页面而不检查是否有冗余信息。结果是一个臃肿的 PDF,类似于使用方法 1 得到的 PDF。PdfSmartCopy查看内容流的字节,并会检测到您一遍又一遍地添加相同的页面。该页面将被重用,方法与方法 2 中的相同。

关于java - iText pdf具有相同内容的多个页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35644926/

相关文章:

java - 使用itext从pdf中提取数学文本

Java 阻塞问题 : Why would JVM block threads in many different classes/methods?

java - Spring : Is this member variable thread-safe?

java - 最新版本的eclipse是否完全兼容windows 10?

java - Gradle 提示它无法将 long 转换为 int,即使该方法需要 long 作为参数

java - 在 iText 中查找不可见文本

android - 如何将 Uint8List 呈现为 pdf?

php - 为 PDF 文件生成唯一的下载链接

android - 下载 PDF 时 InputStream 返回空文件

c# - 如何使用 iTextSharp 创建 pdfformfields?