当前位置: 首页 > 知识库问答 >
问题:

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

卢出野
2023-03-14

如何生成多个页面的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个答案

空谦
2023-03-14

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

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

我看到您正在创建一个名为outerTablePdfPTable对象。我将忽略你对这个表所做的愚蠢的事情(例如,为什么你要将这个表添加到一个段落中?为什么你要将一个colspan 8单元格添加到一个有8列的表中?为什么你要将这个表嵌套到一个有一列的表中?所有这些诡计都非常奇怪),但是有一个outertable,您可以这样做:

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

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

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

为什么这会成为解雇开发人员的理由?因为像这样的应用程序通常生活在云中。在云中,通常要为CPU和带宽付费。开发人员编写需要多倍CPU和带宽的代码,会导致不可接受的成本。在许多情况下,解雇糟糕的开发人员、雇佣稍微贵一点的开发人员和购买稍微贵一点的软件更具成本效益,然后通过在CPU和带宽方面更高效的代码节省大量的长期资金。

方法2:将表添加到一个PdfTemboard中,重用PdfTemboard

请看我对StackOverflow问题的回答,如何调整PdfPTable的大小以适应页面?

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

我创建了一个和表一样大的PdfTemboard

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

现在,我将添加到此模板:

table.writeSelectedRows(0, -1, 0, table.getTotalHeight(), template);

我将包装在一个Image对象中。这并不意味着我们要对表进行光栅化,所有的文本和行都保留为矢量数据

Image img = Image.getInstance(template);

我缩放img,使其适合我心目中的页面大小:

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

现在我把桌子垂直放在中间。

img.setAbsolutePosition(
    0, (PageSize.A4.getHeight() - table.getTotalHeight()) / 2);

如果要多次添加该表,请执行以下操作:

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

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

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

您正在html" target="_blank">内存中创建您的PDF。PDF存储在缓冲区对象中。你可以像这样使用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中的字节发送到响应对象的输出流。确保使用PdfSmartCopy而不是PdfCopyPdfCopy只按原样复制页面,不检查是否有冗余信息。结果是一个膨胀的PDF,类似于使用方法1时得到的PDFPdfSmartCopy查看内容流的字节,并将检测到您正在反复添加同一页面。该页面将以与方法2中相同的方式重用。

 类似资料:
  • 我有一个来自类型“Details”的sortedList,它包含以下内容: 现在,排序后的列表返回所有这些对象,但我想用相同的test0、test1、test2和test3、test4和test5(test3+test3、test4+test4和test5+test5): 我不确定是否是解决此问题的最佳选项。有什么想法吗?应该找到所有test0重复项的两个方法:

  • 我正在使用java。util。ServiceLoader创建轻量级插件框架。 我目前正在努力解决如何拥有多个具有相同FQN的实现类。我想在类路径上拥有同一个插件的两个副本,并且可以访问META-INF/services目录中给出的两个实现类。 以下是一些简单的eclipse项目,它们说明了我的意思:https://docs.google.com/open?id=0B4MxFm-ACB3IUmswN

  • 问题内容: 前一段时间,我花了一些时间来寻找确定两个图像是否相同的方法,以回答[这个问题](http://codingdict.com/questions/100055。我现在面临一个稍微不同的问题:我手头大约有两千张图像,其中一些具有相同的内容,但是彼此缩放/旋转(旋转始终为90°的倍数),还有一个问题。不同的压缩方式和图像格式(主要是jpg,一些png和其他格式)。缩放比例不会超过2:1。我想

  • 我有一个依赖于多个docker容器的应用程序。我使用docker撰写,以便所有容器都在同一个网络中进行容器间通信。但是,我的两个容器在各自的容器中监听相同的端口8080,但是映射到主机上的不同端口: 8072,8073。对于集装箱间的通信,因为我们使用集装箱的端口,这会引起问题吗? 限制条件: 我需要两个容器才能运行我的应用程序。因此,我无法将具有相同内部端口的其他容器隔离到不同的网络 所有容器都

  • 使用两个具有相同标题和/或元描述的页面在谷歌排名上是否有任何惩罚?如果是,罚则是什么? 两个页面位于同一域上。一个页面URL是,另一个页面URL是。两个页面的H1头是相同的,并且都具有相同的元描述。

  • 我是Kafka的初学者。我知道具有相同组id的多个消费者不能在一个主题中使用来自同一个分区的消息。我想知道如果来自一个消费组的多个Kafka消费者从一个分区读取相同的消息会发生什么,为什么这是一件坏事。 。