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

.NET Core 6 MVC用iTextSharp实现DataTable转PDF加自定义页眉页脚报错

问题:.NET Core 6 MVC中iTextSharp添加页眉页脚后PDF生成卡顿崩溃

需求与现状

  • 需求:在.NET Core 6 MVC环境下,使用iTextSharp 5.5.13.3将DataTable中的数据生成PDF,并添加包含公司Logo的自定义页眉和包含公司地址的自定义页脚。
  • 现状:注释页眉页脚事件处理器代码时,可正常生成含DataTable数据的PDF;启用事件处理器后,代码执行到document.Add(table)处时卡顿,最终导致Visual Studio停止运行。

问题原因

在iTextSharp的PdfPageEventHelper的OnStartPage/OnEndPage方法中直接调用document.Add()会触发无限循环:添加页眉/页脚的操作会重新触发页面事件,导致OnStartPage/OnEndPage被反复调用,最终引发死循环和程序崩溃。

修复方案

1. 调整核心处理方法(增加页面边距)

在创建Document实例时,预留足够的页眉页脚空间,避免内容被覆盖:

private void ProcessEMICalendarDocument(DocumentGenerationRequestModel item, List<MemoryStream> templateStreams, string userCode)
{
    var dataTable = dao.GetDataforEMICalendar(item.LoanAccountNo, connectionString);

    if (dataTable != null && dataTable.Rows.Count > 0)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            // 预留页眉页脚空间:左、右、上、下边距(单位:磅)
            using (Document document = new Document(PageSize.A4, 36, 36, 72, 54))
            {
                PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
                HeaderFooter eventHelper = new HeaderFooter();
                // 传入Logo路径(根据实际项目路径调整)
                eventHelper.LogoPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images", "company-logo.png");
                writer.PageEvent = eventHelper;

                document.Open();
                PdfPTable table = CreatePdfPTable(dataTable, 10);

                if (table.Rows.Count > 0)
                {
                    document.Add(table);
                    document.Close();

                    MemoryStream clonedMemoryStream = new MemoryStream(memoryStream.ToArray());
                    clonedMemoryStream.Position = 0;
                    templateStreams.Add(clonedMemoryStream);
                }
                else
                {
                    Console.WriteLine("The PdfPTable has no rows.");
                }
            }
        }
    }
    else
    {
        Console.WriteLine("The DataTable is null or empty.");
    }
}

2. 修复页眉页脚事件处理器类

使用PdfWriter.DirectContent直接绘制页眉页脚,避免触发循环:

public class HeaderFooter : PdfPageEventHelper
{
    private bool addHeader = true;
    private bool addFooter = true;
    // 用于存储Logo路径
    public string LogoPath { get; set; }

    public override void OnStartPage(PdfWriter writer, Document document)
    {
        if (!addHeader) return;

        PdfContentByte cb = writer.DirectContent;
        // 设置页眉位置(距离页面顶部20磅)
        float headerY = document.PageSize.Top - 20;

        // 添加Logo
        if (!string.IsNullOrEmpty(LogoPath) && File.Exists(LogoPath))
        {
            Image logo = Image.GetInstance(LogoPath);
            // 调整Logo大小和位置
            logo.ScaleToFit(80, 40);
            logo.SetAbsolutePosition(document.LeftMargin, headerY - logo.ScaledHeight);
            cb.AddImage(logo);
        }

        // 添加页眉文字(右侧对齐)
        Phrase headerText = new Phrase("公司名称", new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD));
        ColumnText.ShowTextAligned(cb, Element.ALIGN_RIGHT, headerText, document.PageSize.Right - document.RightMargin, headerY, 0);
    }

    public override void OnEndPage(PdfWriter writer, Document document)
    {
        if (!addFooter) return;

        PdfContentByte cb = writer.DirectContent;
        // 设置页脚位置(距离页面底部20磅)
        float footerY = document.Bottom + 20;

        // 添加页脚地址文字(居中对齐)
        Phrase footerText = new Phrase("公司地址:XX市XX区XX路XX号 | 联系电话:XXX-XXXXXXX", new Font(Font.FontFamily.HELVETICA, 10, Font.NORMAL));
        ColumnText.ShowTextAligned(cb, Element.ALIGN_CENTER, footerText, document.PageSize.Width / 2, footerY, 0);

        // 添加页码(右侧对齐)
        Phrase pageNumber = new Phrase($"第 {writer.PageNumber} 页", new Font(Font.FontFamily.HELVETICA, 10, Font.NORMAL));
        ColumnText.ShowTextAligned(cb, Element.ALIGN_RIGHT, pageNumber, document.PageSize.Right - document.RightMargin, footerY, 0);
    }
}

关键注意事项

  • 禁止在OnStartPage/OnEndPage中调用document.Add(),必须通过PdfContentByte直接操作内容
  • 必须预留足够的页面边距,确保页眉页脚不会覆盖正文内容
  • Logo路径要根据实际项目结构调整,确保程序能读取到图片文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 02:57:05