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

如何使用iTextSharp C#生成5000+页大型PDF报表且避免内存异常

如何用iTextSharp(C#)生成大型PDF报表并避免内存异常

问题根源

你的代码核心问题在于一次性将数百万条数据(甚至5亿条)全部存入PdfPTable后才写入文档,所有单元格数据会长期驻留在内存中,直接触发内存溢出。即使是5000页的报表,这种一次性加载的方式也会耗尽内存。

核心优化方案

1. 分批次写入表格,及时释放内存

不要将所有单元格都存在同一个PdfPTable实例中,而是每添加一批数据就写入文档,然后重置表格,让内存只保留当前批次的数据。

2. 启用Writer的即时磁盘刷新

通过配置PdfWriter的压缩和刷新机制,让iTextSharp及时将内存中的数据写入磁盘,而非一直缓存。

3. 复用资源减少内存开销

提前初始化字体、单元格格式等资源,避免在循环中重复创建,减少不必要的内存占用。

4. 关闭非必要的高精度设置

ByteBuffer.HIGH_PRECISION = true会增加内存消耗,非业务必需时建议关闭。

优化后的代码示例

// 初始化文档与Writer
Document pdfDoc = new Document(PageSize.A3.Rotate(), 0, 0, 10, 10);
FileStream stream = new FileStream(fileName, FileMode.Create);
var writer = PdfWriter.GetInstance(pdfDoc, stream);
// 启用全压缩,降低内存缓存
writer.SetFullCompression();
pdfDoc.Open();

// 提前初始化复用资源(避免循环内重复创建)
var headerFont = fontHeaderFontAR;
var cellFont = yourFont;

// 写入表头
if (headerContent != null)
{
    PdfPTable headerTable = new PdfPTable(1);
    headerTable.SpacingBefore = 30f;
    foreach (PDFHeaderItem item in headerContent.items)
    {
        headerTable.AddCell(CreateTitlePDFCell(Lang, item.ItemHeader, headerFont, headerContent));
        headerTable.SpacingBefore = 10f;
    }
    pdfDoc.Add(headerTable);
    // 手动释放表头表格资源
    headerTable = null;
}

// 分批次处理数据,示例每1000行一批(可根据内存情况调整)
int batchSize = 1000;
int totalRows = 500000; // 对应5000+页的实际数据量
for (int batchIndex = 0; batchIndex < totalRows; batchIndex += batchSize)
{
    PdfPTable dataTable = new PdfPTable(1);
    // 计算当前批次的实际行数
    int currentBatchCount = Math.Min(batchSize, totalRows - batchIndex);
    
    for (int i = 0; i < currentBatchCount; i++)
    {
        dataTable.AddCell(CreatePDFCell("TEXT", cell.KeyName, cellFont, cellFormats));
    }
    
    // 写入当前批次表格
    pdfDoc.Add(dataTable);
    // 强制刷新到磁盘,释放内存
    writer.Flush();
    // 释放当前批次表格资源
    dataTable = null;
    // 按需触发垃圾回收(视内存压力调整)
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

pdfDoc.Close();
stream.Close();

额外注意事项

  • 分页加载数据源:如果数据来自数据库,使用分页查询每次只获取当前批次的数据,避免一次性加载全量数据到内存。
  • 监控内存调整批次:根据实际运行环境的内存容量,调整batchSize的大小,找到内存占用和生成速度的平衡点。
  • 避免不必要的对象创建:循环内不要重复实例化字体、单元格样式等可复用对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:45:36