iText7 END_PAGE事件异常:可变页眉显示错误求助
问题分析
你遇到的核心问题是事件触发时机和共享变量的冲突:你的VariableHeaderEventHandler使用了一个共享的header字段存储页眉内容,但iText7的END_PAGE事件并不是在调用AreaBreak时立即触发的——它会延迟到文档关闭阶段才批量处理所有页面的事件。这就导致当所有END_PAGE事件最终执行时,header已经被最后一次循环的赋值("THE FACTORS OF 3")覆盖,所以所有页面都显示同一个页眉。
修复方案
我们需要为每个页面关联独立的页眉内容,而不是使用共享变量。可以利用iText7中PdfPage的自定义属性功能,将每个页面对应的页眉直接存储在页面对象中,事件触发时从当前页面读取对应的页眉即可。
修改后的完整代码
class Program { public static String DEST = "test.pdf"; static void Main(string[] args) { Console.WriteLine("Hello World!"); manipulatePdf(DEST); } public static List<int> getFactors(int n) { List<int> factors = new List<int>(); for (int i = 2; i <= n; i++) { while (n % i == 0) { factors.Add(i); n /= i; } } return factors; } protected static void manipulatePdf(String dest) { PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST)); Document doc = new Document(pdfDoc, PageSize.A4, true); VariableHeaderEventHandler handler = new VariableHeaderEventHandler(); pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, handler); List<int> factors; // 修改循环条件为<=4,才能生成i=4的页面 for (int i = 2; i <= 4; i++) { factors = getFactors(i); if (factors.Count == 1) { doc.Add(new Paragraph("This is a prime number!")); } foreach (int factor in factors) { doc.Add(new Paragraph("Factor: " + factor)); } // 将当前页面的页眉存储到页面的自定义属性中 PdfPage currentPage = pdfDoc.GetLastPage(); currentPage.PutPdfObject("PageHeader", new PdfString($"THE FACTORS OF {i}")); // 最后一页不需要添加AreaBreak,避免空页面 if (i != 4) { doc.Add(new AreaBreak()); } } doc.Close(); } protected class VariableHeaderEventHandler : IEventHandler { public void HandleEvent(Event @event) { PdfDocumentEvent documentEvent = (PdfDocumentEvent)@event; PdfPage page = documentEvent.GetPage(); try { // 从当前页面的自定义属性中读取页眉内容 PdfString headerStr = page.GetPdfObject("PageHeader") as PdfString; string header = headerStr?.ToUnicodeString() ?? string.Empty; new PdfCanvas(page) .BeginText() .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 12) .MoveText(450, 806) .ShowText(header) .EndText() .Stroke(); } catch (IOException e) { // 添加错误日志,方便调试 Console.WriteLine($"Font loading error: {e.Message}"); } } } }
关键修改点说明
- 为每个页面存储独立页眉:在循环中,每次完成当前页面的内容添加后,获取当前页面并将对应的页眉存入页面的自定义属性
PageHeader中。 - 事件中读取页面专属页眉:在
HandleEvent方法里,不再依赖共享变量,而是从触发事件的当前页面中读取专属的页眉内容。 - 修正循环与分页逻辑:
- 将循环条件从
i < 4改为i <= 4,这样才能生成你预期的第三页(对应i=4)。 - 将原有的
300 != i判断改为i != 4,避免最后一页后多出空页面。
- 将循环条件从
这样修改后,每个页面都会显示对应的专属页眉,符合你的预期。
内容的提问来源于stack exchange,提问作者th1rdey3
相关产品推荐
相关产品推荐

