近期.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();
}
}
}