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

时间:2016-02-26 06:23:37

标签: 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();
%>

1 个答案:

答案 0 :(得分:2)

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

方法1:多次添加相同的表格。

我看到您正在创建名为PdfPTable的{​​{1}}对象。我将忽略你对这个表所做的愚蠢的事情(例如为什么要将这个表添加到段落中?为什么要将一个带有colspan 8的单元格添加到一个包含8列的表中?为什么要嵌套?把这个表放到一个带有单列的表中?所有这些恶作剧真的很奇怪),但是有了outerTable,你可以这样做:

outertable

这将添加表for (int i = 0; i < x; i++) { document.add(outerTable); document.newPage(); } 次,它将为每个表启动一个新页面。这也是评论中的人们建议你的,虽然代码看起来非常优雅,但它不会产生优雅的PDF。那就是:如果你是我的员工,如果你这样做,我会解雇你。

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

为什么这会成为解雇开发人员的理由?因为像这样的应用程序通常存在于云中。在云中,通常需要支付CPU和带宽。编写需要多个CPU和带宽的代码的开发人员会导致成本无法接受。在许多情况下,解雇不良开发人员,雇用稍微昂贵的开发人员并购买稍贵的软件,然后通过在CPU和频段方面更高效的代码长期节省大量资金更具成本效益-width。

方法2:将表格添加到x,重复使用PdfTemplate

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

的回答

在此示例中,我创建了一个名为PdfTemplate的{​​{1}}。我知道我希望桌子有多宽(PdfPTable),但我事先并不知道它会有多高。所以我锁定了宽度,我添加了我需要添加的单元格,然后我可以像这样计算表格的高度:table

我创建的PageSize.A4.getWidth()与表格一样大:

table.getTotalHeight()

我现在将PdfTemplate添加到此模板中:

PdfContentByte canvas = writer.getDirectContent();
PdfTemplate template = canvas.createTemplate(
    table.getTotalWidth(), table.getTotalHeight());

我将table包装在table.writeSelectedRows(0, -1, 0, table.getTotalHeight(), template); 对象中。 这并不意味着我们对表进行栅格化,所有文本和行都保留为矢量数据。

table

我缩放Image以使其符合我想到的页面大小:

Image img = Image.getInstance(template);

现在我将桌子垂直放在中间位置。

img

如果您想多次添加表格,请执行以下操作:

img.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());

方法1有什么区别?好吧,通过使用img.setAbsolutePosition( 0, (PageSize.A4.getHeight() - table.getTotalHeight()) / 2); ,您正在创建表单XObject 表单XObject 外部到页面流的内容流。 表单XObject 仅存储在PDF文件中一次,并且可以多次重复使用,例如,在文档的每一页上。

方法3:创建一个包含单个页面的PDF文档;多次连接文件

您正在内存中创建PDF。 PDF存储在for (int i = 0; i < x; i++) { document.add(img); document.newPage(); } 对象中。您可以使用PdfTemplate这样阅读此PDF:

buffer

然后您重复使用此内容:

PdfReader

现在,您可以将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代替responsePdfSmartCopy只是复制页面AS-IS而不检查是否存在冗余信息。结果是一个臃肿的PDF类似于你使用方法1时得到的PDF。PdfCopy查看内容流的字节,并将检测到你一遍又一遍地添加相同的页面。该页面将以与方法2中相同的方式重复使用。