如何生成每页上具有相同内容的多个页面的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();
%>
答案 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
代替response
。 PdfSmartCopy
只是复制页面AS-IS而不检查是否存在冗余信息。结果是一个臃肿的PDF类似于你使用方法1时得到的PDF。PdfCopy
查看内容流的字节,并将检测到你一遍又一遍地添加相同的页面。该页面将以与方法2中相同的方式重复使用。