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
相关产品推荐
相关产品推荐

