.NET WebAPI生成Excel
Webform中,生成Excel,一般是设置response.Content.Headers.ContentType输出类型为application/vnd.ms-excel,思路都是这样的。
每一个API方法都这样做一下,也是可以的。参考:http://www.cnblogs.com/jizhong/p/3592088.html
更好的做法是,客户端请求的时候,设置Requst.Header的Accept:application/vnd.ms-excel。目的:客户端设置了什么类型,服务端针对性的去调用相应方法,返回相应类型的文件流,可配置,可扩展,Formatter相关不写死在具体方法中,剥离出来。
var _exportToExcel = function (clientId) { var url = serviceBase + 'api/clientStatusLog?clientId='+clientId; return $http.get(url, { headers: { Accept: 'application/vnd.ms-excel' }, responseType: 'arraybuffer' }).then(function (response) { return response; }); }
服务端在WebApiConfig中添加一种Formatter,我们添加自己写的类的对象,类继承自System.Net.Http.Formatting.BufferedMediaTypeFormatter的MediaTypeFormatter。类中重写了父类的CanWriteType,设置type == typeof(ClientStatusLogReportDto)或者IEnumerable<ClientStatusLogReportDto>时候,CanWriteType方法返回true. 这样在Controller方法中,直接return ClientStatusLogReportDto或List<ClientStatusLogReportDto>, 自己写的Formatter方法会进行生成Excel的逻辑,调用重写父类的WriteToStream等方法,实现生成指定格式的数据,返回响应。
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Formatters config.Formatters.Add(new ClientExcelormatter()); config.Formatters.Add(new ClientStatusLogExcelormatter()); } }
public class ClientStatusLogExcelormatter: BufferedMediaTypeFormatter { private const string MIME_TYPE = "application/vnd.ms-excel"; private HSSFWorkbook workBook; public ClientStatusLogExcelormatter() { // Add the supported media type. SupportedMediaTypes.Add(new MediaTypeHeaderValue(MIME_TYPE)); } public override bool CanWriteType(System.Type type) { if (type == typeof(ClientStatusLogReportDto)) { return true; } else { Type enumerableType = typeof(IEnumerable<ClientStatusLogReportDto>); return enumerableType.IsAssignableFrom(type); } } public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content) { var clientList = value as IEnumerable<ClientStatusLogReportDto>; var curRole = OwinContextHelper.GetUserRole(); if (clientList != null) { Initialize(); GenerateData(clientList); workBook.Write(writeStream); } else { var singleObj = value as ClientStatusLogReportDto; if (singleObj == null) { throw new InvalidOperationException("Cannot serialize type"); } } var filename = "clientStatusLog.xls"; content.Headers.ContentType = new MediaTypeHeaderValue(MIME_TYPE); content.Headers.Add("x-filename", filename); content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); content.Headers.ContentDisposition.FileName = filename; } private void Initialize() { workBook = new HSSFWorkbook(); ////create a entry of DocumentSummaryInformation DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = "Centria Healthcare"; workBook.DocumentSummaryInformation = dsi; ////create a entry of SummaryInformation SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); si.Subject = "Client Status Log Export"; workBook.SummaryInformation = si; } private void GenerateData(IEnumerable<ClientStatusLogReportDto> clientList) { HSSFSheet oHSSFSheet = (HSSFSheet)workBook.CreateSheet("Client List"); //==================================== string[] columnList = { "Name", "Funding Source", "Current Status", "Status", "Timestamp", "Creator", "Updater"}; int colCount = columnList.Length; int rowNum = 0; int colNum = 0; IFont fontHeader = workBook.CreateFont(); fontHeader.FontName = "Arial"; fontHeader.Boldweight = (short)FontBoldWeight.Bold; fontHeader.FontHeightInPoints = 10; IFont fontRow = workBook.CreateFont(); fontRow.FontName = "Arial"; fontRow.FontHeightInPoints = 10; HSSFCellStyle headerStyle = (HSSFCellStyle)workBook.CreateCellStyle(); HSSFCellStyle normalRowStyle = (HSSFCellStyle)workBook.CreateCellStyle(); headerStyle.SetFont(fontHeader); headerStyle.BorderBottom = BorderStyle.Thin; headerStyle.BorderLeft = BorderStyle.Thin; headerStyle.BorderRight = BorderStyle.Thin; headerStyle.BorderTop = BorderStyle.Thin; headerStyle.Alignment = HorizontalAlignment.Center; headerStyle.VerticalAlignment = VerticalAlignment.Center; headerStyle.FillForegroundColor = HSSFColor.Black.Index; normalRowStyle.SetFont(fontRow); normalRowStyle.BorderBottom = BorderStyle.Thin; normalRowStyle.BorderLeft = BorderStyle.Thin; normalRowStyle.BorderRight = BorderStyle.Thin; normalRowStyle.BorderTop = BorderStyle.Thin; normalRowStyle.Alignment = HorizontalAlignment.Center; normalRowStyle.VerticalAlignment = VerticalAlignment.Center; normalRowStyle.FillForegroundColor = HSSFColor.Black.Index; HSSFRow header = (HSSFRow)oHSSFSheet.CreateRow(0); for (int i = 0; i < colCount; i++) { HSSFCell oCell = (HSSFCell)header.CreateCell(i); oCell.SetCellType(CellType.String); oCell.SetCellValue(columnList[i]); oCell.CellStyle = headerStyle; } //write each item. foreach (ClientStatusLogReportDto client in clientList) { HSSFRow dataRow = (HSSFRow)oHSSFSheet.CreateRow(++rowNum); colNum = 0; foreach (PropertyInfo proInfo in typeof(ClientStatusLogReportDto).GetProperties()) { object v = proInfo.GetValue(client); string value = string.Empty; if (v != null) { value = v.ToString(); } HSSFCell cell = (HSSFCell)dataRow.CreateCell(colNum++); cell.SetCellType(CellType.String); cell.SetCellValue(value); cell.CellStyle = normalRowStyle; } } } public override bool CanReadType(Type type) { return false; } }
public class ClientStatusLogController : ApiController { private readonly IClientStatusLogService _clientStatusLogService; private readonly IMembershipService _membershipService; public ClientStatusLogController(IClientStatusLogService clientStatusLogService, IMembershipService membershipService) { this._clientStatusLogService = clientStatusLogService; this._membershipService = membershipService; } public List<ClientStatusLogReportDto> GetList(Guid clientId) { var list = _clientStatusLogService.GetList(clientId); var listDto = new List<ClientStatusLogReportDto>(); foreach (var item in list) { var dto = Mapper.Map<ClientStatusLog, ClientStatusLogReportDto>(item); dto.CreatedBy = _membershipService.GetUserRealName(dto.CreatedBy); dto.CreatedBy = _membershipService.GetUserRealName(dto.ModifiedBy); listDto.Add(dto); } return listDto; } }