上篇文章已经介绍Excel能够分为Excel2003和Excel2007两种版本,Excel2003在POI中使用HSSF对象,一个sheet最多容许65536条数据,处理较少数据时可使用,可是处理百万数据时Excel2003确定容纳不了;Excel2007在POI中使用XSSF对象,最多容许一个sheet存储1048576条数据,表示其已经能够支持百万数据,可是在实际运行可能中还存在问题,缘由是POI报表所产生的对象,单元格对象,字体对象,都不会销毁,致使了可能存在OutOfMemoryError(OOM)内存溢出风险。java
对于百万数据Excel的导出,基本只限于讨论Excel2007版本的使用方法。ApachePOI提供三种方式解决大数据量的数据导入导出:git
在互联网时代,百万数据常常产生,有多种多样的缘由须要数据导出github
使用POI的XSSFWORK对象进行导出Excel报表,是将全部的数据一次性到单元格对象,并保存到内存中,当单元格所有建立完成才会一次性写入到Excel进行导出。当达到百万级别的数据导出时,随着单元格对象的不断建立,内存中的数据愈来愈多,直到OOM。POI的SXSSFWORK对象,是专门用于处理大数据量的Excel导出的。apache
在实例化SXSSFWork对象时,能够指定内存中所产生的POI对象数量(默认100),一旦内存对象个数达到指定数量,就将内存中的数据写入到磁盘,就能够将内存中数据进行销毁,以此循环直到Excel导出完成app
仍是以用户数据为例子xss
在FileUtil中添加ide
对以前的作了一些小改动字体
package com.cn.greemes.common.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.poi.excel.BigExcelWriter; import cn.hutool.poi.excel.ExcelUtil; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; /** * 文件操做 */ public class FileUtil { public static final String SYS_TEM_DIR =System.getProperty("java.io.tmpdir")+ File.separator; public void downloadExcel(List<Map<String, String>> list, HttpServletResponse response) throws IOException { String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; File file = new File(tempPath); BigExcelWriter writer = ExcelUtil.getBigWriter(file); // 一次性写出内容,使用默认样式,强制输出标题 writer.write(list, true); SXSSFSheet sheet = (SXSSFSheet)writer.getSheet(); //上面须要强转SXSSFSheet 否则没有trackAllColumnsForAutoSizing方法 sheet.trackAllColumnsForAutoSizing(); //列宽自适应 // writer.autoSizeColumnAll(); //response为HttpServletResponse对象 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); ServletOutputStream out = response.getOutputStream(); // 终止后删除临时文件 file.deleteOnExit(); writer.flush(out, true); //此处记得关闭输出Servlet流 IoUtil.close(out); } public void downloadExcelBySXSSF(List<Map<String, String>> list, HttpServletResponse response) throws IOException { String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; File file = new File(tempPath); //2.建立工做簿 SXSSFWorkbook workbook = new SXSSFWorkbook(); //3.构造sheet Sheet sheet =workbook.createSheet(); //建立表头 Row row = sheet.createRow(0); Map<String,String> mapfirst = list.get(0); String listHead = null; AtomicInteger headersAi = new AtomicInteger(); for (String key : mapfirst.keySet()) { Cell cell = row.createCell(headersAi.getAndIncrement()); cell.setCellValue(key); } AtomicInteger datasAi = new AtomicInteger(1); Cell cell =null; for(Map<String, String> map : list){ Row dataRow = sheet.createRow(datasAi.getAndIncrement()); int i=0; for (String key : map.keySet()) { Cell cell1 = dataRow.createCell(datasAi.getAndIncrement()); String value= (String)map.get(key); cell = dataRow.createCell(i); cell1.setCellValue(value); i++; } } String fileName = URLEncoder.encode("用户信息.xlsx", "UTF-8"); response.setContentType("application/octet-stream"); response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1"))); response.setHeader("filename", fileName); workbook.write(response.getOutputStream()); } }
@ApiOperation("导出用户数据") @RequestMapping(value = "/export2", method = RequestMethod.GET) @ResponseBody public void export2(HttpServletResponse response, @RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) throws UnsupportedEncodingException, IOException { Page<MesAdmin> adminList = adminService.list(keyword, pageSize, pageNum); List<Map<String,String>> list = new ArrayList(); //由于只有七条数据,因此作了屡次循环添加数据 for(int i=0;i<149795;i++) { for (MesAdmin umsAdmin : adminList.getRecords()) { Map<String, String> map = new HashMap<>(6); DateFormat d1 = DateFormat.getDateInstance(); map.put("姓名", umsAdmin.getUsername()); map.put("邮箱", umsAdmin.getEmail()); map.put("昵称", umsAdmin.getNickName()); map.put("备注信息", umsAdmin.getNote()); map.put("建立时间", d1.format( umsAdmin.getCreateTime())); String loginTime =""; if(umsAdmin.getLoginTime()!=null){ loginTime=d1.format( umsAdmin.getLoginTime()); } map.put("最后登陆时间",loginTime ); list.add(map); } } fileUtil.downloadExcelBySXSSF(list,response); }
原本要介绍数据的导出,但是发现百万级别的数据导出也须要介绍一下,明天介绍数据的导出大数据
github地址:https://github.com/bangbangzhou/greemes/tree/masterui