NPOI 导出列太多或者数据太多爆内存

近期.net mvc 开发的项目运行一段时间的项目,突然用户反馈导出数据出现500错误。后面看到日志是内存爆了。我是使用NPOI 组件来进行导出,服务器也有8G内存,之前一直好好的。然后发现导出的execl数据才几万,列大概有2000多列,怎么这么容易爆。

可惜没有办法客户不想加配置,那就只能把数据网硬盘里面搞了。因为从数据库抓出来的数据需要多很多逻辑处理,所以没有办法直接从数据库直接导出到文件。

原本想过使用多个文件最后合并的方式,但是我比较懒不想搞,所以就查了一下 NPOI是支持硬盘存储临时数据的。

好了,下面是代码:

//---------------------------------------创建下载文档---------------------------------------

static IWorkbook workbook = null;

static string NewfileName;

//allen add 20240616使用SXSSFWorkbook方法,这个是放入硬盘的临时文件

public static string CreatModelToExcel1(int columns, DataTable data, string sheetName, bool isColumnWritten, string fileName)

{

fileName = System.AppDomain.CurrentDomain.BaseDirectory + "DownExcel/" + fileName;

NewfileName = System.AppDomain.CurrentDomain.BaseDirectory + "DownExcel/" + fileName;

if (data == null)

{

throw new ArgumentNullException("data");

}

if (string.IsNullOrEmpty(sheetName))

{

throw new ArgumentNullException(sheetName);

}

if (string.IsNullOrEmpty(fileName))

{

throw new ArgumentNullException(fileName);

}

//IWorkbook workbook = null;

if (fileName.IndexOf(".xlsx", StringComparison.Ordinal) > 0)

{

//workbook = new XSSFWorkbook();

workbook = new SXSSFWorkbook();//allen 0617

//workbook = new HSSFWorkbook();

}

else if (fileName.IndexOf(".xls", StringComparison.Ordinal) > 0)

{

workbook = new HSSFWorkbook();

}

FileStream fs = null;

try

{

using (fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))

{

SXSSFSheet sheet; //allen 0617

if (workbook != null)

{

sheet =(SXSSFSheet)workbook.CreateSheet(sheetName);//allen 0617

}

else

{

return "";//返回文件为空

}

int j;

int count;

//写入DataTable的列名,写入单元格中

if (isColumnWritten)

{

var row = sheet.CreateRow(0);

int ci = 0;

for (j = 1; j < data.Columns.Count; ++j)

{

#region 分割数据添加单元格

//处理数据

}

count = 1;

//设置自适应宽度 //2022-10-24

for (int columnNum = 0; columnNum <= data.Columns.Count; columnNum++)

{

sheet.TrackAllColumnsForAutoSizing();

sheet.AutoSizeColumn(columnNum);

int columnWidth = sheet.GetColumnWidth(columnNum) / 256;

for (int rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++)

{

IRow currentRow = sheet.GetRow(rowIndex);

ICell cell = row.GetCell(columnNum);

int contextLength = Encoding.UTF8.GetBytes(cell.ToString()).Length;//获取当前单元格的内容宽度

columnWidth = columnWidth < contextLength ? contextLength : columnWidth;

}

sheet.SetColumnWidth(columnNum, columnWidth * 280);

}

}

else

{

count = 0;

}

//遍历循环datatable具体数据项

int i;

for (i = 0; i < data.Rows.Count; ++i)

{

}

++count;

//每3000次和最后一次调用保存的方法---没用了

//if (count % 3000 == 0 || count == data.Rows.Count)

//{

// SaveExcel();

// initWorkBook();

// sheet = workbook.GetSheet(sheetName);

//}

}

//将文件流写入到excel

workbook.Write(fs);

workbook.Close();

((SXSSFWorkbook)workbook).Dispose();

//返回文件名外面直接访问下载

return fileName;

}

}

catch (IOException ioex)

{

throw new IOException(ioex.Message);

}

catch (Exception ex)

{

throw new Exception(ex.Message);

}

finally

{

if (fs != null)

{

fs.Close();

}

}

}

相关推荐
勘察加熊人2 小时前
forms实现俄罗斯方块
c#
艾妮艾妮5 小时前
C语言常见3种排序
java·c语言·开发语言·c++·算法·c#·排序算法
小码编匠6 小时前
.NET 验证码生成神器基于 SkiaSharp 的高性能方案
后端·c#·.net
专注VB编程开发20年6 小时前
Aspose.words,Aspose.cells,vb.net,c#加载许可证,生成操作选择:嵌入的资源
c#·word·.net·vb.net
andy55206 小时前
.NET 使用 WMQ 连接Queue 发送 message 实例
xml·c#·wmq·c# 连接wmq·发送消息到wmq
破罐子不摔6 小时前
【C#使用S7.NET库读取和写入西门子PLC变量】
java·c#·.net
杰尼杰尼丶7 小时前
Winform MQTT客户端连接方式
c#·winform
weixin_307779138 小时前
C#实现HiveQL建表语句中特殊数据类型的包裹
开发语言·数据仓库·hive·c#
lixy5798 小时前
C# WPF 命令机制(关闭CanExecute自动触发,改手动)
c#·wpf
天地长久.8 小时前
C# N层架构和解耦
c#·解耦·多层架构