自学内容网 自学内容网

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


原文地址:https://blog.csdn.net/luohai326/article/details/140649303

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!