You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}");
            }
        }
    }
}

关键修改点说明

  1. 为每个页面存储独立页眉:在循环中,每次完成当前页面的内容添加后,获取当前页面并将对应的页眉存入页面的自定义属性PageHeader中。
  2. 事件中读取页面专属页眉:在HandleEvent方法里,不再依赖共享变量,而是从触发事件的当前页面中读取专属的页眉内容。
  3. 修正循环与分页逻辑:
    • 将循环条件从i < 4改为i <= 4,这样才能生成你预期的第三页(对应i=4)。
    • 将原有的300 != i判断改为i != 4,避免最后一页后多出空页面。

这样修改后,每个页面都会显示对应的专属页眉,符合你的预期。

内容的提问来源于stack exchange,提问作者th1rdey3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:24:52