Commit 9e4eefc5 by jianshuqin

优化:组件导出内存释放

parent 1f4f2198
using Bailun.DC.Common;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
namespace Bailun.DC.Services.Component
{
......@@ -70,80 +69,177 @@ namespace Bailun.DC.Services.Component
return list;
}
public static byte[] DataTableToExcel(IDictionary<string, string> listHeader, DataTable SourceTable)
public static byte[] DataTableToExcel(IDictionary<string, string> listHeader, DataTable table)
{
XSSFWorkbook workbook = null;
MemoryStream ms = null;
ISheet sheet = null;
XSSFRow headerRow = null;
try
byte[] b = null;
int headerCount = listHeader?.Count ?? 0;
int tableCount = table?.Rows.Count ?? 0;
if (headerCount > 0 || tableCount > 0)
{
workbook = new XSSFWorkbook();
ms = new MemoryStream();
sheet = workbook.CreateSheet();
headerRow = (XSSFRow)sheet.CreateRow(0);
IFont fontTitle = workbook.CreateFont();//新建一个字体样式对象
fontTitle.IsBold = true;//设置字体加粗样式
fontTitle.FontHeightInPoints = 12;//设置字体大小
var styleTitle = workbook.CreateCellStyle();
if (listHeader?.Count > 0)
IWorkbook workbook = null;
MemoryStream ms = null;
try
{
listHeader.ForEach((l, i) =>
{
var cell = headerRow.CreateCell(i);
cell.CellStyle = styleTitle;
cell.SetCellValue(l.Value);
});
if (SourceTable != null)
workbook = new HSSFWorkbook();
int excelMaxRowCount = 65535;
for (int i = 0; (i == 0 && tableCount == 0) || (i * excelMaxRowCount < tableCount); i++)
{
for (int i = 0; i < SourceTable.Rows.Count; i++)
ISheet sheet = workbook.CreateSheet($"Sheet{i + 1}");
//标题行
IRow headerRow = sheet.CreateRow(0);
//新建一个字体样式对象
IFont fontTitle = workbook.CreateFont();
//设置字体加粗样式
fontTitle.IsBold = true;
//设置字体大小
fontTitle.FontHeightInPoints = 12;
//单元格样式
ICellStyle styleTitle = workbook.CreateCellStyle();
//标题
if (headerCount > 0)
{
XSSFRow dataRow = (XSSFRow)sheet.CreateRow(i + 1);
listHeader.ForEach((l, col) =>
{
if (SourceTable.Columns.Contains(l.Key))
ICell cell = headerRow.CreateCell(col);
cell.CellStyle = styleTitle;
cell.SetCellValue(l.Value);
});
}
else
{
foreach (DataColumn column in table.Columns)
{
var cell = headerRow.CreateCell(column.Ordinal);
cell.CellStyle = styleTitle;
cell.SetCellValue(column.ColumnName);
}
}
//数据
for (int row = (i * excelMaxRowCount), j = 0; (row < tableCount && j < excelMaxRowCount); row++, j++)
{
IRow dataRow = sheet.CreateRow(row + 1);
if (headerCount > 0)
{
listHeader.ForEach((l, col) =>
{
if (table.Columns.Contains(l.Key))
{
dataRow.CreateCell(col).SetCellValue(table.Rows[row][l.Key]?.ToString());
}
});
}
else
{
foreach (DataColumn column in table.Columns)
{
dataRow.CreateCell(col).SetCellValue(SourceTable.Rows[i][l.Key]?.ToString());
dataRow.CreateCell(column.Ordinal).SetCellValue(table.Rows[row][column]?.ToString());
}
});
}
}
}
//写入workbook
workbook.Write(ms = new MemoryStream());
b = ms.ToArray();
}
catch (Exception ex)
{
throw ex;
}
else
finally
{
foreach (DataColumn column in SourceTable.Columns)
if (workbook != null)
{
var cell = headerRow.CreateCell(column.Ordinal);
cell.CellStyle = styleTitle;
cell.SetCellValue(column.ColumnName);
workbook.Close();
workbook = null;
}
for (int rowIndex = 0; rowIndex < SourceTable.Rows.Count; rowIndex++)
if (ms != null)
{
XSSFRow dataRow = (XSSFRow)sheet.CreateRow(rowIndex + 1);
foreach (DataColumn column in SourceTable.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(SourceTable.Rows[rowIndex][column].ToString());
}
ms.Close();
ms.Dispose();
ms = null;
}
}
workbook.Write(ms);
}
catch
{
return null;
}
finally
return b;
}
public static byte[] DataReaderToExcel(IDictionary<string, string> listHeader, IDataReader reader, int dataCount)
{
byte[] data = null;
if (listHeader?.Count > 0)
{
sheet = null;
headerRow = null;
workbook = null;
IWorkbook workbook = null;
MemoryStream ms = null;
try
{
workbook = new HSSFWorkbook();
int excelMaxRowCount = 65535;
for (int i = 0; (i * excelMaxRowCount < dataCount); i++)
{
ISheet sheet = workbook.CreateSheet($"Sheet{i + 1}");
//标题行
IRow headerRow = sheet.CreateRow(0);
//新建一个字体样式对象
IFont fontTitle = workbook.CreateFont();
//设置字体加粗样式
fontTitle.IsBold = true;
//设置字体大小
fontTitle.FontHeightInPoints = 12;
//单元格样式
ICellStyle styleTitle = workbook.CreateCellStyle();
listHeader.ForEach((l, col) =>
{
var cell = headerRow.CreateCell(col);
cell.CellStyle = styleTitle;
cell.SetCellValue(l.Value);
});
for (int row = 0; row < excelMaxRowCount && reader.Read(); row++)
{
IRow dataRow = sheet.CreateRow(row + 1);
listHeader.ForEach((header, col) =>
{
if (reader[header.Key] != null)
{
dataRow.CreateCell(col).SetCellValue(reader[header.Key].ToString());
}
});
}
}
//写入workbook
workbook.Write(ms = new MemoryStream());
data = ms.ToArray();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (workbook != null)
{
workbook.Close();
workbook = null;
}
if (reader != null)
{
reader.Dispose();
reader = null;
}
if (ms != null)
{
ms.Close();
ms.Dispose();
ms = null;
GC.Collect();
}
}
}
return ms.ToArray();
}
return data;
}
}
public static class IEnumerableExtension
......
......@@ -76,13 +76,16 @@ namespace Bailun.DC.Services.Component
return dto;
}
public IList<ColumnDTO> GetListColumn(QueryFilterDTO queryFilter = null)
public IList<ColumnDTO> GetListColumn(QueryFilterDTO queryFilter = null, QueryDTO entity = null)
{
IList<ColumnDTO> list = default(IList<ColumnDTO>);
if (queryFilter != null && !string.IsNullOrWhiteSpace(queryFilter.Code))
{
QueryDTO entity = this.Get(queryFilter.Code);
if (entity == null)
{
entity = this.Get(queryFilter.Code);
}
if (entity != null && (!string.IsNullOrWhiteSpace(entity.ColumnValue)))
{
switch (entity.ColumnType)
......@@ -222,12 +225,15 @@ namespace Bailun.DC.Services.Component
return list;
}
public PageListDTO GetListData(QueryFilterDTO queryFilter)
public PageListDTO GetListData(QueryFilterDTO queryFilter, QueryDTO entity = null)
{
PageListDTO pageList = new PageListDTO();
if (queryFilter != null && !string.IsNullOrWhiteSpace(queryFilter.Code))
{
QueryDTO entity = this.Get(queryFilter.Code);
if (entity == null)
{
entity = this.Get(queryFilter.Code);
}
if (entity != null && (!string.IsNullOrWhiteSpace(entity.DataValue)))
{
switch (entity.DataType)
......@@ -293,24 +299,11 @@ namespace Bailun.DC.Services.Component
#region 数据库表或视图/SQL
case DataTypeEnum.Table:
case DataTypeEnum.Sql:
DynamicParameters sqlparam = new DynamicParameters();
int fetch = (queryFilter.pageSize > 0 ? queryFilter.pageSize : int.MaxValue).Value;
int offset = (((queryFilter.CurrentPage > 1 ? queryFilter.CurrentPage : 1) - 1) * fetch).Value;
//过虑条件SQL
string whereSql = this.GetFilterSql(queryFilter, ref sqlparam);
//排序条件SQL
string orderbySql = this.GetOrderBySql(queryFilter, entity);
string fromSql = $"FROM {(entity.DataType == DataTypeEnum.Table ? $"[dbo].[{entity.DataValue}]" : $"( {entity.DataValue} )")} AS A {whereSql}";
string totalSql = $"SELECT COUNT(*) {fromSql}";
string dataSql = $"SELECT A.* {fromSql} ORDER BY {orderbySql} LIMIT {offset} , {fetch}";
using (var db = (entity.DataDB == DBEnum.DataWareHouse ? DW_DB : DB))
(int, IDataReader) reader = this.GetListDataReader(queryFilter, entity);
using (reader.Item2)
{
pageList.TotalCount = db.QueryFirstOrDefault<int>(totalSql, sqlparam);
if (pageList.TotalCount > 0)
{
var reader = db.ExecuteReader(dataSql, sqlparam);
pageList.List.Load(reader);
}
pageList.TotalCount = reader.Item1;
pageList.List.Load(reader.Item2);
}
break;
......@@ -473,15 +466,32 @@ namespace Bailun.DC.Services.Component
byte[] b = default(byte[]);
if (queryFilter != null)
{
IList<ColumnDTO> listColumn = this.GetListColumn(queryFilter);
QueryDTO entity = this.Get(queryFilter.Code);
IList<ColumnDTO> listColumn = this.GetListColumn(queryFilter, entity);
if (listColumn != null)
{
//数据类型
DataTypeEnum?[] dataTypes = { DataTypeEnum.Table, DataTypeEnum.Sql };
//列标题
IDictionary<string, string> listHeader = listColumn.Where(l => l.IsExport == true || (l.IsExport == null && l.IsHide != true)).ToDictionary(l => l.Prop, l => l.Name);
//全部数据导出
queryFilter.CurrentPage = null;
queryFilter.pageSize = null;
PageListDTO pageList = this.GetListData(queryFilter);
if (listColumn?.Count > 0)
if (!string.IsNullOrWhiteSpace(entity.DataValue) && dataTypes.Contains(entity.DataType))
{
b = DataTableToExcel(listColumn.Where(l => l.IsExport == true || (l.IsExport == null && l.IsHide != true)).ToDictionary(l => l.Prop, l => l.Name), pageList.List);
(int, IDataReader) reader = this.GetListDataReader(queryFilter, entity);
using (reader.Item2)
{
b = DataReaderToExcel(listHeader, reader.Item2, reader.Item1);
}
}
else
{
PageListDTO pageList = this.GetListData(queryFilter, entity);
if (listColumn?.Count > 0)
{
b = DataTableToExcel(listHeader, pageList.List);
}
}
}
}
......@@ -578,7 +588,7 @@ namespace Bailun.DC.Services.Component
private string GetOrderBySql(QueryFilterDTO queryFilter, QueryDTO entity = null)
{
string sql = "1";
string sql = string.Empty;
if (queryFilter?.ListOrder?.Where(l => l != null).Count() > 0)
{
......@@ -611,5 +621,23 @@ namespace Bailun.DC.Services.Component
return sql;
}
private (int, IDataReader) GetListDataReader(QueryFilterDTO queryFilter, QueryDTO entity)
{
(int, IDataReader) reader = (0, null);
DynamicParameters sqlparam = new DynamicParameters();
int fetch = (queryFilter.pageSize > 0 ? queryFilter.pageSize : int.MaxValue).Value;
int offset = (((queryFilter.CurrentPage > 1 ? queryFilter.CurrentPage : 1) - 1) * fetch).Value;
//过虑条件SQL
string whereSql = this.GetFilterSql(queryFilter, ref sqlparam);
//排序条件SQL
string orderbySql = this.GetOrderBySql(queryFilter, entity);
string fromSql = $"FROM {(entity.DataType == DataTypeEnum.Table ? $"[dbo].[{entity.DataValue}]" : $"( {entity.DataValue} )")} AS A {whereSql}";
string totalSql = $"SELECT COUNT(*) {fromSql}";
string dataSql = $"SELECT A.* {fromSql} {(!string.IsNullOrWhiteSpace(orderbySql) ? $"ORDER BY {orderbySql}" : string.Empty) } LIMIT {offset} , {fetch}";
var db = (entity.DataDB == DBEnum.DataWareHouse ? DW_DB : DB);
reader = (db.QueryFirstOrDefault<int>(totalSql, sqlparam), db.ExecuteReader(dataSql, sqlparam));
return reader;
}
}
}
......@@ -63,9 +63,10 @@ namespace Bailun.DC.Web.Areas.Component.Controllers
[HttpPost]
public ActionResult Export(QueryFilterDTO queryFilter)
{
byte[] data = null;
try
{
byte[] data = new QueryService().Export(queryFilter);
data = new QueryService().Export(queryFilter);
return File(data, "text/plain", "ImportAttendeesInfol.xls");
}
catch (Exception ex)
......@@ -73,6 +74,11 @@ namespace Bailun.DC.Web.Areas.Component.Controllers
ResultDTO result = new ResultDTO() { Message = ex.Message };
return Json(result);
}
finally
{
data = null;
GC.Collect();
}
}
}
......
......@@ -121,7 +121,7 @@
if (l.type == "daterange" && l.value.constructor == Array && l.value.length > 1) {
filter.operator = "between";
if (l.value[0].constructor == Date && l.value[1].constructor == Date) {
filter.value = [l.value[0].format("yyyy-MM-dd"), l.value[1].format("yyyy-MM-dd")];
filter.value = [l.value[0].format("yyyy-MM-dd"), l.value[1].format("yyyy-MM-dd")].join(",");
} else {
filter.value = l.value.join(",");
}
......@@ -286,7 +286,14 @@
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8'
}
}).then(function (json) {
saveAs(json.bodyBlob, 'Export_' + (new Date().format("yyyyMMddhhmmss")) + '.xlsx');
var ext = "xlsx";
if (json.headers && json.headers.map && json.headers.map["content-disposition"] && json.headers.map["content-disposition"].length > 0) {
var fileInfo = json.headers.map["content-disposition"][0].split(';');
var fileName = fileInfo && fileInfo.length > 2 && fileInfo[1];
ext = fileName && fileName.split(".").length > 1 && fileName.split(".")[1];
}
var exportName = (that.setting.listCrumb && that.setting.listCrumb.length > 0 ? that.setting.listCrumb.join("") : ('Export')) + "_" + (new Date().format("yyyyMMddhhmm"));
saveAs(json.bodyBlob, exportName + "." + ext);
}).catch(function (error) {
that.$message(error.message || " 未知错误!");
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment