如何在不使用扩展或脚本的情况下为XSLT生成的动态尺寸PDF添加页码?
解决方案:用iTextSharp PdfStamper为动态尺寸PDF添加页码
因为文档尺寸不固定,直接用XSL-FO定义页脚无法适配每页的实际尺寸,你可以通过iTextSharp的PdfStamper工具,先生成不带页码的PDF,再遍历每页动态添加页码,完全不需要扩展或JavaScript。
核心思路
- 先生成无页码的PDF(沿用你现有的XSLT→XSL-FO→PDF流程,输出到内存流即可)
- 用
PdfReader读取该PDF,通过PdfStamper遍历每一页 - 获取每页的实际尺寸,计算页码的位置(比如底部居中)
- 直接在每页的内容层绘制页码文本
代码示例
// 假设你已经完成无页码PDF的生成,输出到内存流ms中 MemoryStream ms = GeneratePdfWithoutPageNumbers(); // 替换为你的实际生成逻辑 // 读取无页码PDF内容 PdfReader reader = new PdfReader(ms.ToArray()); int totalPages = reader.NumberOfPages; // 创建PdfStamper处理PDF,输出到新的内存流 using (MemoryStream outputStream = new MemoryStream()) using (PdfStamper stamper = new PdfStamper(reader, outputStream)) { // 初始化字体 BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); float fontSize = 10f; float margin = 10f; // 页码距离页边的间距 // 遍历每页添加页码 for (int pageNum = 1; pageNum <= totalPages; pageNum++) { // 获取当前页的实际尺寸 Rectangle pageSize = reader.GetPageSize(pageNum); // 获取当前页的顶层内容层(确保页码显示在所有内容上方) PdfContentByte contentByte = stamper.GetOverContent(pageNum); // 设置字体和大小 contentByte.SetFontAndSize(baseFont, fontSize); // 定义页码文本格式 string pageText = $"第 {pageNum} 页 / 共 {totalPages} 页"; // 计算文本宽度,用于实现居中对齐 float textWidth = baseFont.GetWidthPoint(pageText, fontSize); // 计算页码位置:底部居中,距离底部margin float xPos = pageSize.Left + margin + (pageSize.Width - 2 * margin - textWidth) / 2; float yPos = pageSize.Bottom + margin; // 绘制页码 contentByte.BeginText(); contentByte.SetTextMatrix(xPos, yPos); contentByte.ShowText(pageText); contentByte.EndText(); } // 关闭Stamper,确保内容写入输出流 stamper.Close(); // 将带页码的PDF保存到文件或返回使用 File.WriteAllBytes("output_with_page_numbers.pdf", outputStream.ToArray()); }
关键细节
- 动态适配页面尺寸:通过
reader.GetPageSize(pageNum)获取每页的实际宽高,不管页面是横向、纵向还是自定义尺寸,都能正确计算页码位置 - 页码层级:用
GetOverContent确保页码显示在所有内容上方,若需要放在内容下方,改用GetUnderContent - 字体与对齐:通过
BaseFont设置字体,计算文本宽度实现居中,也可以根据需求调整为左对齐或右对齐
内容的提问来源于stack exchange,提问作者Vinicius Henrique
相关产品推荐
相关产品推荐

