页码看起来只是 PDF 中一个很小的元素,但对于报告、合同、说明书等多页文档来说非常实用。尤其是在打印、审阅或引用文档内容时,清晰的页码可以帮助读者快速定位页面。
如果 PDF 是由 Java 程序批量生成或处理的,逐个手动添加页码显然并不现实。这种情况下,可以直接在程序中遍历 PDF 页面,并将当前页码和总页数自动添加到每一页。
本文将介绍如何使用 Spire.PDF for Java 为已有 PDF 添加类似 "第 1 页,共 10 页" 的动态页码。
安装 Spire.PDF for Java
如果使用 Maven,可以在项目的 pom.xml 文件中添加以下仓库和依赖:
xml
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.pdf</artifactId>
<version>12.8.1</version>
</dependency>
</dependencies>
Java 给 PDF 添加"第 X 页,共 Y 页"页码
Spire.PDF for Java 提供了几个用于处理动态页码的字段:
PdfPageNumberField:获取当前页的页码PdfPageCountField:获取 PDF 的总页数PdfCompositeField:将多个动态字段组合成一段文本
因此,我们不需要自己为每一页生成不同的页码文本,而是可以将当前页码和总页数组合成 "第 {0} 页,共 {1} 页" 的格式。
下面是完整代码:
java
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.automaticfields.PdfCompositeField;
import com.spire.pdf.automaticfields.PdfPageCountField;
import com.spire.pdf.automaticfields.PdfPageNumberField;
import com.spire.pdf.graphics.PdfBrush;
import com.spire.pdf.graphics.PdfBrushes;
import com.spire.pdf.graphics.PdfTrueTypeFont;
import java.awt.Font;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
public class AddPageNumbers {
public static void main(String[] args) {
// 加载 PDF 文档
PdfDocument document = new PdfDocument();
document.loadFromFile("示例文档.pdf");
// 设置页码字体和颜色
PdfTrueTypeFont font = new PdfTrueTypeFont(
new Font("Microsoft YaHei", Font.PLAIN, 10), true);
PdfBrush brush = PdfBrushes.getBlack();
// 创建当前页码字段和总页数字段
PdfPageNumberField pageNumberField = new PdfPageNumberField();
PdfPageCountField pageCountField = new PdfPageCountField();
// 将两个字段组合成"第 X 页,共 Y 页"
PdfCompositeField pageNumber = new PdfCompositeField(
font,
brush,
"第 {0} 页,共 {1} 页",
pageNumberField,
pageCountField
);
// 遍历 PDF 中的所有页面
for (int i = 0; i < document.getPages().getCount(); i++) {
PdfPageBase page = document.getPages().get(i);
Dimension2D pageSize = page.getSize();
// 测量页码文本宽度,用于计算居中位置
String text = "第 " + (i + 1) + " 页,共 "
+ document.getPages().getCount() + " 页";
Dimension2D textSize = font.measureString(text);
// 计算页码位置
double x = (pageSize.getWidth() - textSize.getWidth()) / 2;
double y = pageSize.getHeight() - 30;
// 在当前页面底部绘制页码
pageNumber.setLocation(new Point2D.Double(x, y));
pageNumber.draw(page.getCanvas(), 0, 0);
}
// 保存结果文档
document.saveToFile("添加页码后的PDF.pdf");
document.dispose();
}
}
下面分步骤看一下这段代码的实现过程。
第一步:加载 PDF 文档
首先创建 PdfDocument 对象,并加载需要添加页码的 PDF:
java
PdfDocument document = new PdfDocument();
document.loadFromFile("示例文档.pdf");
这里处理的是已有 PDF。如果 PDF 本身也是由程序生成的,同样可以在文档最终保存之前执行后面的页码添加操作。
第二步:设置页码的字体和颜色
接下来设置页码使用的字体和颜色:
java
PdfTrueTypeFont font = new PdfTrueTypeFont(
new Font("Microsoft YaHei", Font.PLAIN, 10), true);
PdfBrush brush = PdfBrushes.getBlack();
这里使用 10 磅微软雅黑和黑色文字。
实际使用时,可以根据 PDF 的整体排版调整字体、字号和颜色。例如正式报告中的页码通常不需要太大,9~11 磅一般就足够了。
如果程序部署在 Linux 或服务器环境中,还需要注意系统是否安装了代码中指定的字体。
第三步:创建动态页码
页码的核心部分是下面三个字段:
java
PdfPageNumberField pageNumberField = new PdfPageNumberField();
PdfPageCountField pageCountField = new PdfPageCountField();
其中:
PdfPageNumberField 表示当前页面的页码,而 PdfPageCountField 表示整个 PDF 的总页数。
然后通过 PdfCompositeField 将两个字段组合起来:
java
PdfCompositeField pageNumber = new PdfCompositeField(
font,
brush,
"第 {0} 页,共 {1} 页",
pageNumberField,
pageCountField
);
其中 {0} 对应当前页码,{1} 对应总页数。
假设 PDF 一共有 8 页,最终得到的页码就是:
text
第 1 页,共 8 页
第 2 页,共 8 页
第 3 页,共 8 页
...
第 8 页,共 8 页
这种方式的好处是无需提前知道 PDF 到底有多少页,页码和总页数会根据实际文档自动生成。S
第四步:将页码添加到每一页
接下来遍历 PDF 中的所有页面:
java
for (int i = 0; i < document.getPages().getCount(); i++) {
PdfPageBase page = document.getPages().get(i);
Dimension2D pageSize = page.getSize();
// ...
}
这里没有直接假设所有页面尺寸完全相同,而是分别读取每一页的大小。
这样对于同时包含 A4 页面、横向页面或其他尺寸页面的 PDF,也可以根据当前页面重新计算页码位置。
第五步:让页码在页面底部居中
如果直接写死 X 坐标,页码可能无法真正居中。因此可以先计算实际显示文本的宽度:
java
String text = "第 " + (i + 1) + " 页,共 "
+ document.getPages().getCount() + " 页";
Dimension2D textSize = font.measureString(text);
然后根据页面宽度计算 X 坐标:
java
double x = (pageSize.getWidth() - textSize.getWidth()) / 2;
double y = pageSize.getHeight() - 30;
其中:
x用于让页码水平居中y用于控制页码距离页面底部的位置
最后将组合字段绘制到页面:
java
pageNumber.setLocation(new Point2D.Double(x, y));
pageNumber.draw(page.getCanvas(), 0, 0);
Spire.PDF 支持通过页面 Canvas 在指定坐标绘制内容,因此除了居中页码,也可以通过调整 X、Y 坐标将页码放到左下角或右下角。
修改页码格式
如果不需要显示总页数,可以将页码格式改成:
java
"第 {0} 页"
得到:
text
第 1 页
第 2 页
第 3 页
也可以使用更加简洁的格式:
java
"{0} / {1}"
结果类似:
text
1 / 10
如果文档页脚中还需要显示报告名称,也可以直接加入固定文本:
java
"项目报告 | 第 {0} 页,共 {1} 页"
这样无需改变其他页码处理逻辑。
注意 PDF 底部是否有足够空间
给已有 PDF 添加页码时,有一点需要特别注意:添加页码并不会自动为原有内容腾出页脚空间。
例如,原 PDF 中的表格、正文或签名区域已经延伸到页面底部,此时直接添加页码可能与原有内容重叠。
遇到这种情况,可以适当调整:
java
double y = pageSize.getHeight() - 30;
中的 Y 坐标,将页码移动到合适的位置。
如果 PDF 本身也是由程序生成的,更合适的做法是在生成页面内容时提前预留页脚区域。
总结
在批量生成报告、合同或其他多页 PDF 时,通过 Java 自动添加页码可以省去大量重复操作。
Spire.PDF for Java 提供的 PdfPageNumberField 和 PdfPageCountField 可以分别获取当前页码和总页数,再通过 PdfCompositeField 将它们组合成 "第 X 页,共 Y 页" 等格式。
在此基础上,只需遍历 PDF 页面并计算合适的坐标,就可以将页码统一添加到每一页的底部,也可以根据实际需求进一步调整页码格式、字体和位置。