如何生成每个页面上具有相同内容的多个页面的 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);
我把
table
在 Image
内目的。这并不意味着我们正在栅格化表格,所有文本和行都保留为 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/