对于我们来说,java导出数据成excel或其他数据文件,或者下载资源是开发中的家常便饭, 但是在导出的时候,如果点击一个按钮导出几百万条数据,如果不作处理的话很可能会出现一系列的问题. 这里介绍打包成zip压缩包下载

针对大量数据导出excel, 这里有几种办法:
1. 每到一定数量就分成一个sheet
2. 每到一定数量分成一个excel,压缩成zip包打包下载
3. 控制导出的数据量,或者分页查询
4. 加缓存,用POI官方的api
SXSSFWorkbook workbook = new SXSSFWorkbook(rowCache);

我这边用的是2和4 , 整体的思路就是,如果是小数目的数据,直接下载excel,如果是大量数据,先转换成一个个excle放在一个临时文件夹中, 然后打包临时文件夹成zip包返回给浏览器,然后删除临时文件夹

[下载文件的工具类]

先准备好自己定义的工具类,之后的方法里面都需要用到这个工具类, 包括设置两头一流, 压缩文件,删除文件夹等


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Encoder;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;@SuppressWarnings("restriction")
public class FileDownloadUtils {private static final Logger logger = LoggerFactory.getLogger(FileDownloadUtils.class);/*** 编译下载的文件名* @param filename* @param agent* @return* @throws IOException*/public static String encodeDownloadFilename(String filename, String agent)throws IOException {if (agent.contains("Firefox")) { // 火狐浏览器filename = "=?UTF-8?B?"+ new BASE64Encoder().encode(filename.getBytes("utf-8"))+ "?=";filename = filename.replaceAll("\r\n", "");} else { // IE及其他浏览器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+"," ");}return filename;}/*** 创建文件夹;* @param path*/public static void createFile(String path) {File file = new File(path);//判断文件是否存在;if (!file.exists()) {//创建文件;file.mkdirs();}}/*** 生成.zip文件;* @param path* @throws IOException*/public static ZipOutputStream craeteZipPath(String path) throws IOException{ZipOutputStream zipOutputStream = null;File file = new File(path+DateUtils.getDateWx()+".zip");zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)));File[] files = new File(path).listFiles();FileInputStream fileInputStream = null;byte[] buf = new byte[1024];int len = 0;if(files!=null && files.length > 0){for(File excelFile:files){String fileName = excelFile.getName();fileInputStream = new FileInputStream(excelFile);//放入压缩zip包中;zipOutputStream.putNextEntry(new ZipEntry(path + "/"+fileName));//读取文件;while((len=fileInputStream.read(buf)) >0){zipOutputStream.write(buf, 0, len);}//关闭;zipOutputStream.closeEntry();if(fileInputStream != null){fileInputStream.close();}}}/*if(zipOutputStream !=null){zipOutputStream.close();}*/return zipOutputStream;}/*** //压缩文件* @param srcfile   要压缩的文件数组* @param zipfile  生成的zip文件对象*/public static void ZipFiles(java.io.File[] srcfile, File zipfile) throws Exception {byte[] buf = new byte[1024];FileOutputStream fos = new FileOutputStream(zipfile);ZipOutputStream out = new ZipOutputStream(fos);for (int i = 0; i < srcfile.length; i++) {FileInputStream in = new FileInputStream(srcfile[i]);out.putNextEntry(new ZipEntry(srcfile[i].getName()));int len;while ((len = in.read(buf)) > 0) {out.write(buf, 0, len);}out.closeEntry();in.close();}out.close();fos.flush();fos.close();}/*** 删除文件夹及文件夹下所有文件* @param dir* @return*/public static boolean deleteDir(File dir) {if (dir == null || !dir.exists()){return true;}if (dir.isDirectory()) {String[] children = dir.list();//递归删除目录中的子目录下for (int i=0; i<children.length; i++) {boolean success = deleteDir(new File(dir, children[i]));if (!success) {return false;}}}// 目录此时为空,可以删除return dir.delete();}/*** 生成html* @param msg* @return* @author zgd* @time 2018年6月25日11:47:07*/public static String getErrorHtml(String msg) {StringBuffer sb = new StringBuffer();sb.append("<html>");sb.append("<head>");sb.append("<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>");sb.append("</head>");sb.append("<body>");sb.append("<div id='errorInfo'> ");sb.append("</div>");sb.append("<script>alert('"+msg+"')</script>");sb.append("</body>");sb.append("</html>");return sb.toString();}/*** 设置下载excel的响应头信息* @param response* @param request* @param agent* @param fileName* @throws IOException* @author zgd* @time 2018年6月25日11:47:07*/public static void setExcelHeadInfo(HttpServletResponse response, HttpServletRequest request, String fileName)  {try {// 获取客户端浏览器的类型String agent = request.getHeader("User-Agent");// 对文件名重新编码String encodingFileName = FileDownloadUtils.encodeDownloadFilename(fileName, agent);// 告诉客户端允许断点续传多线程连接下载response.setHeader("Accept-Ranges", "bytes");//文件后缀response.setContentType("application/vnd.ms-excel;charset=UTF-8");response.setHeader("Content-Disposition", "attachment; filename=" + encodingFileName);} catch (IOException e) {logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() +"发生的异常是: ",e);throw new RuntimeException(e);}}/*** 设置下载zip的响应头信息* @param response* @param fileName 文件名* @param request* @throws IOException* @author zgd* @time 2018年6月25日11:47:07*/public static void setZipDownLoadHeadInfo(HttpServletResponse response, HttpServletRequest request, String fileName) throws IOException {// 获取客户端浏览器的类型String agent = request.getHeader("User-Agent");response.setContentType("application/octet-stream ");// 表示不能用浏览器直接打开response.setHeader("Connection", "close");// 告诉客户端允许断点续传多线程连接下载response.setHeader("Accept-Ranges", "bytes");// 对文件名重新编码String encodingFileName = FileDownloadUtils.encodeDownloadFilename(fileName, agent);response.setHeader("Content-Disposition", "attachment; filename=" + encodingFileName);}}

1.控制层接收参数

/*** 导出商家订单数据列表的excel文件** @param request* @author zgd* @time 2018年6月5日14:47:21*/@RequestMapping(value = "/exportStoreOrderList")public void exportStoreOrderList(HttpServletRequest request, HttpServletResponse response) {/** 从service层获取List的数据,此处省略*/List<Map<String, Object>> list = data;//导出excel// 创建Excel文件,每个excel限制10000条数据,超过则打包zipint size = 10000;//每次缓存1000条到内存,其余写到磁盘int rowCache = 1000;String fileName = "商家订单数据-" + DateUtils.getDateWx();// 创建Excel文件,每个excel限制10000条数据,超过则打包zipint size = 10000;//每次缓存1000条到内存,其余写到磁盘int rowCache = 1000;String fileName = "商家订单数据-" + DateUtils.getDateWx();//导出exceltry {//excel文件个数int n = list.size() / size + 1;if (list != null) {SXSSFWorkbook workbook = getStoreOrderExcel(list, rowCache);if (n == 1) {//下载单个exclefileName = fileName + ".xls";FileDownloadUtils.downloadExcel(request, response, fileName, workbook);} else {fileName = "批量" + fileName + ".zip";String realPath = request.getSession().getServletContext().getRealPath("WEB-INF");//创建临时文件夹保存excelString tempDir = realPath + "/tempDir/" + DateUtils.getDateWx();List<File> files = getStoreOrderExcels(tempDir, size, list, rowCache);String zipPath = tempDir + "\\" + fileName;//下载zipFileDownloadUtils.downloadZip(request, response, fileName, files, zipPath);//删除tempDir文件夹和其中的excel和zip文件boolean b = FileDownloadUtils.deleteDir(new File(realPath + "\\tempDir"));if (!b) {throw new RuntimeException("tempDir文件夹及其中的临时Excel和zip文件删除失败");}}}}catch (Exception e) {try {if (!response.isCommitted()) {response.setContentType("text/html;charset=utf-8");response.setHeader("Content-Disposition", "");String html = FileDownloadUtils.getErrorHtml("下载失败");response.getOutputStream().write(html.getBytes("UTF-8"));}} catch (IOException e1) {e1.printStackTrace();}}}

2. getStoreOrderExcel方法解析

 /*** 将数据库查出来的商家订单数据,创建成excel* @param list  商家订单数据* @param rowCache  缓冲的行数* @return*/private SXSSFWorkbook getStoreOrderExcel(List<Map<String, Object>> list, int rowCache) {//如果rowCache是1000,就是每次读取1000条数据到缓存中SXSSFWorkbook workbook = new SXSSFWorkbook(rowCache);/**....设置行,列,塞入数据**/return workbook;}

2.1 这里分成两条线: 下载excel和下载zip

2.2 下载excel支线

2.2.1 downloadExcel方法解析
/*** 下载excel** @param request* @param response* @param fileName* @param workbook* @throws Exception* @author zgd* @time 2018年6月25日11:47:07*/private void downloadExcel(HttpServletRequest request, HttpServletResponse response, String fileName, SXSSFWorkbook workbook) {//一个流两个头//设置下载excel的头信息FileDownloadUtils.setExcelHeadInfo(response, request, fileName);// 写出文件ServletOutputStream os = null;try {os = response.getOutputStream();workbook.write(os);} catch (IOException e) {logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + "发生的异常是: ", e);throw new RuntimeException(e);} finally {try {if (os != null) {os.flush();os.close();}if (workbook != null) {workbook.close();}} catch (Exception e1) {logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + "发生的异常是: ", e1);throw new RuntimeException(e1);}}}

下载excel支线完毕

2.3 下载zip支线

2.3.1 getStoreOrderExcels方法解析,先将大量数据转化成批量的excel临时文件
 /*** 将数据转成多个excel文件放在项目中** @param tempDir* @param size     每个excel的数据的行数* @param list     数据* @param rowCache 下载时缓存的行数* @throws Exception* @author zgd* @time 2018年6月25日11:47:07*/private List<File> getStoreOrderExcels( String tempDir, int size, List<Map<String, Object>> list, int rowCache) throws Exception {//excel文件个数int n = list.size() / size + 1;FileDownloadUtils.createFile(tempDir);List<File> files = new ArrayList<File>();  //声明一个集合,用来存放多个Excel文件路径及名称for (int i = 0; i < n; i++) {int max = Math.min((i + 1) * size, list.size());//避免将需要合并的单元格拆分成两个表 , 如果最后的一条主订单数据等于下一条数据,max+1while (max < list.size() - 1 && list.get(max).get("orderNo").equals(list.get(max + 1).get("orderNo"))) {max++;}List<Map<String, Object>> partList = list.subList(i * size, max);SXSSFWorkbook wb = getStoreOrderExcel(partList, rowCache);//生成一个excelString path = tempDir + "\\商家订单数据-" + (i + 1) + ".xlsx";generateExcelToPath(wb, path);//excel添加到files中files.add(new File(path));}return files;}
2.3.1.1 generateExcelToPath方法,将生成excel到指定路径
/*** 生成excel到指定路径* @param wb* @param path* @throws Exception*/private void generateExcelToPath(SXSSFWorkbook wb, String path) throws Exception {FileOutputStream fos = null;try {fos = new FileOutputStream(path);wb.write(fos);} finally {if (fos != null) {fos.flush();fos.close();}if (wb != null) {wb.close();}}}
2.3.2 downloadZip方法解析,打包下载zip
/*** 将批量文件打包下载成zip* @param request* @param response* @param zipName     下载的zip名* @param files       要打包的批量文件* @param zipPath     生成的zip路径* @throws Exception*/private void downloadZip(HttpServletRequest request, HttpServletResponse response, String zipName, List<File> files, String zipPath)throws Exception {File srcfile[] = new File[files.size()];File zip = new File(zipPath);for (int i = 0; i < files.size(); i++) {srcfile[i] = files.get(i);}//生成.zip文件;FileInputStream inStream = null;ServletOutputStream os = null;try {//设置下载zip的头信息FileDownloadUtils.setZipDownLoadHeadInfo(response, request, zipName);os = response.getOutputStream();FileDownloadUtils.ZipFiles(srcfile, zip);inStream = new FileInputStream(zip);byte[] buf = new byte[4096];int readLength;while (((readLength = inStream.read(buf)) != -1)) {os.write(buf, 0, readLength);}}  finally {if (inStream != null) {inStream.close();}if (os != null) {os.flush();os.close();}}}

zip下载支线完毕

3.附 打成zip包

直接用工具类

/*** //压缩文件* @param srcfile   要压缩的文件数组* @param zipfile  生成的zip文件对象*/public static void ZipFiles(java.io.File[] srcfile, File zipfile) throws Exception {byte[] buf = new byte[1024];FileOutputStream fos = new FileOutputStream(zipfile);ZipOutputStream out = new ZipOutputStream(fos);for (int i = 0; i < srcfile.length; i++) {FileInputStream in = new FileInputStream(srcfile[i]);out.putNextEntry(new ZipEntry(srcfile[i].getName()));int len;while ((len = in.read(buf)) > 0) {out.write(buf, 0, len);}out.closeEntry();in.close();}out.close();fos.flush();fos.close();}

4. 删除临时文件夹

/*** 删除文件夹及文件夹下所有文件* @param dir* @return*/public static boolean deleteDir(File dir) {if (dir == null || !dir.exists()){return true;}if (dir.isDirectory()) {String[] children = dir.list();//递归删除目录中的子目录下for (int i=0; i<children.length; i++) {boolean success = deleteDir(new File(dir, children[i]));if (!success) {return false;}}}// 目录此时为空,可以删除return dir.delete();}

java批量文件打包成压缩成zip下载和大量数据导出excel时的处理方法相关推荐

  1. Java 批量文件不打包下载_【Java】Java批量文件打包下载zip

    /* * 另存为 */ @RequestMapping("/saveAs.do") public @ResponseBody void saveAs(String filePath ...

  2. 如何将文件打包、压缩并分割成制定大小?

    如何将文件打包.压缩并分割成制定大小? (如何在linux下实现Windows中winrar和winzip等压缩软件所提供的打包压缩分割功能) 将大文件或目录打包.压缩并分割成制定大小的文件,这在将数 ...

  3. linux中如何压缩单个文件大小,Linux 将文件打包、压缩并分割成指定大小

    打包文件: tar -cvf .tar 分割文件: split -b 3G -d -a .tar .tar. //使用split命令,-b 3G 表示设置每个分割包的大小,单位还是可以k // -d ...

  4. linux tar zcxf,tar/gzip/zip文件打包、压缩命令

    一.tar打包备份工具 1.命令功能 tar 将多个文件或目录打包在一起,可用通过调用gzip或zip实现压缩.解压的命令:tar不仅可以多多个文件进行打包,还可以对多个文件打包后进行压缩. 2.语法 ...

  5. tar/gzip/zip文件打包、压缩命令

    一.tar打包备份工具 1.命令功能 tar 将多个文件或目录打包在一起,可用通过调用gzip或zip实现压缩.解压的命令:tar不仅可以多多个文件进行打包,还可以对多个文件打包后进行压缩. 2.语法 ...

  6. Linux新手上路(六):文件打包和解压缩

    1.概念讲解 在讲 Linux 上的压缩工具之前,有必要先了解一下常见常用的压缩包文件格式.在 Windows 上最常见的不外乎这两种 .zip,.7z 后缀的压缩文件.而在 Linux 上面常见的格 ...

  7. system.img解包打包工具_好程序员云计算学习路线分享文件打包及压缩

    好程序员云计算学习路线分享文件打包及压缩 好程序员 建议针对目录 Demo: 复制未打包的文件到远程主机 [root@yangs ~]# du -sh /etc 39M /etc [root@yang ...

  8. Java程序员从笨鸟到菜鸟之(一百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表...

    在上一篇博客中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅仅简单的读取office中的数据.尤其是在生 ...

  9. 在vue中把数据导出Excel文件

    在vue中把数据导出Excel文件 第一次尝试写文章 在vue中把数据导出成Excel格式的文件,话不多,上代码: 第一步我们要先安装几个集成的插件 npm install -S file-saver ...

最新文章

  1. 程序员法律考试(7)-民法(4)
  2. Spring IoC(一)IoC容器的设计与实现:BeanFactory与ApplicationContext
  3. 二叉树的定义、性质、存储
  4. Android开发之高仿百度地图底部滑出菜单
  5. java jsonp 接口_jsonp使用,spring4.x对jsonp的支持
  6. 那位标榜技术驱动的开发者去哪了?
  7. [转]docker入门(利用docker部署web应用)
  8. C++:53---菱形继承、虚继承
  9. 常见查找算法之—二分查找
  10. 身份证号码前六位查询表
  11. 网页飘窗效果,jsp页面飘窗浮窗,html飘窗浮窗,点叉号关闭飘窗
  12. 解决使用feign调用服务时携带token
  13. IPv6- Haproxy1.5.8 支持IPv6测试详情
  14. ar vr内容制作_AR和VR品牌内容:探索与观众建立联系的新方式
  15. 信号量优先级反转问题记录(总是遗忘)
  16. uboot环境下mmc操作_uboot mmc命令详解
  17. 吴裕雄--天生自然 高等数学学习:导数的几何意义
  18. C语言青蛙过河游戏超详细教程【附源码】
  19. 如何部署一台云服务器并且和域名绑定
  20. 【知识蒸馏】Masked Generative Distillation

热门文章

  1. form表单提交后提示成功信息
  2. CentOS7 中注册服务并随系统启动
  3. Methods to Control Your Own Feelings One
  4. keil报错: ERROR 118 (ERRONEOUS REFERENCE TO EXTERNAL VARIABLES) 解决方案及原因
  5. 内推网创始人黄小亮:拒绝猎头的P2P招聘
  6. 浅谈Servlet与JSP
  7. CSS特效-下雨天效果
  8. 005_解密饿了么大前端团队
  9. 中国城市资本流动问题探索(Python)
  10. 大数据开发:大数据背景下的数据库选型