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

ASP.NET Core Razor Page导出PDF添加页码遇Document已关闭错误

解决iText转换HTML到PDF时添加页码触发的"Document was closed"异常

问题场景

在ASP.NET Core Razor Page项目中,尝试给导出的PDF每页底部添加「第X页/共Y页」格式的页码时,触发异常:

iText.Kernel.Exceptions.PdfException: 'Document was closed. It is impossible to execute action.'

错误发生在代码行int pageCount = pdfDocument.GetNumberOfPages();,原代码如下:

using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(pdfHtml)))
{
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PdfWriter writer = new PdfWriter(byteArrayOutputStream);
    PdfDocument pdfDocument = new PdfDocument(writer);
    pdfDocument.SetDefaultPageSize(PageSize.A4.Rotate());

    HtmlConverter.ConvertToPdf(stream, pdfDocument);
    int pageCount = pdfDocument.GetNumberOfPages();
    for (int i = 1; i <= pageCount; i++)
    {
        Document doc = new Document(pdfDocument);
        doc.ShowTextAligned(new Paragraph("Page " + i + " of " + pageCount),
            pdfDocument.GetDefaultPageSize().GetWidth() - 50, 30, i, TextAlignment.RIGHT, VerticalAlignment.BOTTOM, 0);
    }

    pdfDocument.Close();
    return File(byteArrayOutputStream.ToArray(), "application/pdf", "AssetTaggingDetails.pdf");
}

问题原因

HtmlConverter.ConvertToPdf(stream, pdfDocument)方法执行完毕后,会自动关闭传入的PdfDocument对象,导致后续调用pdfDocument.GetNumberOfPages()时,因文档已关闭而抛出异常。

解决方案

通过配置转换属性阻止ConvertToPdf自动关闭文档,同时优化代码结构避免重复创建Document实例:

using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(pdfHtml)))
{
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PdfWriter writer = new PdfWriter(byteArrayOutputStream);
    PdfDocument pdfDocument = new PdfDocument(writer);
    pdfDocument.SetDefaultPageSize(PageSize.A4.Rotate());

    // 配置转换属性,禁止转换后关闭文档
    ConverterProperties properties = new ConverterProperties();
    properties.SetCloseDocument(false);

    HtmlConverter.ConvertToPdf(stream, pdfDocument, properties);

    int pageCount = pdfDocument.GetNumberOfPages();
    Document doc = new Document(pdfDocument); // 仅创建一次Document实例

    for (int i = 1; i <= pageCount; i++)
    {
        PageSize currentPageSize = pdfDocument.GetPage(i).GetPageSize();
        Paragraph pageNumberPara = new Paragraph($"Page {i} of {pageCount}")
            .SetFontSize(10);

        doc.ShowTextAligned(pageNumberPara,
            currentPageSize.GetWidth() - 50,
            30,
            i,
            TextAlignment.RIGHT,
            VerticalAlignment.BOTTOM,
            0);
    }

    doc.Close();
    pdfDocument.Close();
    return File(byteArrayOutputStream.ToArray(), "application/pdf", "AssetTaggingDetails.pdf");
}

关键修改点

  • 添加ConverterProperties并设置SetCloseDocument(false),阻止转换方法自动关闭PdfDocument
  • 将Document实例移到循环外创建,避免重复初始化造成的资源浪费
  • 使用当前页面的PageSize而非默认尺寸,适配可能存在的不同页面大小
  • 替换Encoding.ASCII为Encoding.UTF8,避免HTML中的中文或特殊字符乱码
  • 调整关闭顺序:先关闭Document,再关闭PdfDocument,确保资源释放顺序正确

内容的提问来源于stack exchange,提问作者ahmed salah abd elaziz elbarba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:32:47