最近的一个项目比较忙,一直没时间过来跟新博客。今天过来分享一下在此项目中遇到的一个小问题:导出Excel;相信导出Excel这个功能是特别常见的,也有很多的方式。好了,不多说了,直接说说自己遇到的各种坑,我后台用的是poi导出。

  首先,说一下需求,想要的结果就是:“符合导出条件时,正常导出,并弹出提示框让用户选下载地址,不符合导出条件时,提示用户不能导出,还要在用户导出的同时将导出按钮禁用,当导出成功后,再将导出按钮放开“

  (我首先会将我做的全过程的思路和所遇到的问题和解决方法说一下,干货会在下面贴出来)

    1、因为我们整个框架习惯用异步请求,所以一开始我使用ajax异步请求导出Excel,结果发现导出不了,后台程序也跑完了,日志也记录了,,就是没有出现excel,更别说提示框了,网上查了很多,都说是因为ajax和后台交流用的是字符流,浏览器是不会识别你让他下载的,所以此路不通。(也有小伙伴说用ajax同步,也试了,不行。又填上了一个坑。。。。)

  2、然后就准备用form表单submit提交导出,试了一下,发现可以啊,很高兴,但是问题又来了,form表单提交后页面其实刷新了,如果不符合导出条件我该怎么提示用户呢?新跳转一个页面吗?感觉这样不太合适,因为用户辛辛苦苦输入了半天的条件,然后等了半天后台校验(涉及到大数据量),结果等来的是跑到另一个页面跟你说不能导出,如果是我我会崩溃的,等了半天不说,奶奶个腿,我输入半天的查询条件还得重新输入,这个不能忍。。好吧,这种方法不行,然后试着从后台往jsp页面写脚本,但是也发现根本不执行,也就纳闷了,最后,网上有一位小伙伴说用一个iframe的隐藏域,如果不符合条件的话,再用流的方式将问题写回来,最终问题解决了(代码将会统一贴在下面)。

  3、这样感觉很完美了,但是问题还没有完全解决,还有一个禁用按钮的问题,这个问题想想很简单,用户点击导出时将按钮禁用,导出完成后传回来一个标志,然后再将按钮放开,但是问题来了,这个标志怎么穿回来?一开始我想当然的想和错误提示一样的结局方案,发现不行因为,我导出Excel已经将response流给用掉了,我不可能在用流的方式将标志写回来了。这样就会导致我放不开导出按钮,那老板就不同意了,加班加点的找方法。终于,让我找到了一个解决思路,用cookie来做。具体思路就是:用户点击导出后,禁用按钮,然后js写个定时器轮训找cookie,在将文件流写出后,我会放一个cookie在浏览器中,那么此时js就能找到这个cookie了,找到后,首先将定时器给干掉,再将cookie给干掉(有点过河拆桥的感觉,哈哈),然后将导出按钮给放开。

  (虽然问题解决了,但是cookie和定时器轮训还是有一点不靠谱,希望大家有更好的解决方法,请大家不吝赐教,谢谢!!!)

  前台代码:

  1. <button class="btn btn-sm btn-success" type="submit" id="detailEp" onclick="return exportCheck(true);" forbid="yes">
  2. <i class="icon-arrow-right bigger-110"></i> 导出
  3. </button>

  4. <script>
  5. $(function() {
  6. var timer = "";
  7. });
  8.  
  9. //点击导出按钮时禁用导出按钮
  10. $("#myForm").submit(function() {
  11. $("button[type=submit]",this).attr("disabled","disabled");
  12. //提交导出后定时去查看有没有导出成功
  13. timer = setInterval(refrashPg,1000);
  14. })
  15.  
  16. //导出成功后会放开导出按钮的禁用
  17. function refrashPg() {
  18. if (getCk() =="1") {
  19. clearInterval(timer);
  20. $("#detailEp").removeAttr("disabled");
  21. }
  22. delCk();
  23. }
  24. //js获取到cookie
  25. function getCk() {
  26. debugger
  27. var ck = document.cookie.split(";");
  28. var ckname = "";
  29. for (var i = 0;i<ck.length;i++) {
  30. var arr = ck[i].split("=");
  31. if (arr[0] =="updtstatus") {
  32. ckname = arr[1];
  33. break;
  34. }
  35. }
  36. return ckname;
  37. }
  38. //js删除掉cookie
  39. function delCk() {
  40. var exp = new Date();
  41. var name = "updtstatus";
  42. exp.setTime(exp.getTime()-1000);
  43. var cval = getCk();
  44. document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
  45. }
  46. }
  1. </script>

  后台导出代码就是普通的Java POI代码:

  1. public void buildExcelDocument(Map<String, Object> obj,String fileName,String type,
  2. HttpServletRequest request, HttpServletResponse response)
  3. throws Exception {
  4. HSSFWorkbook workbook = new HSSFWorkbook();
  5. if ("1".equals(type)) {
  6. List<Map<String, Object>> contentList = (List<Map<String, Object>>) obj.get("content");
  7. HSSFSheet sheet = workbook.createSheet("sheet1");//创建Excel的版本是2003-2007(xls) 如果需要2010的话,用 XSSFSheet
  8. Map<String,String> titleList = (Map<String, String>) obj.get("title");
  9. //表头的key 对应内容listMap中的map的key
  10. List<String> mkey = new ArrayList<String>();
  11. //表头的value 表头
  12. List<String> mvalue = new ArrayList<String>();
  13. Iterator<Entry<String, String>> it = titleList.entrySet().iterator();
  14. while(it.hasNext()){
  15. @SuppressWarnings("rawtypes")
  16. java.util.Map.Entry entry = (java.util.Map.Entry)it.next();
  17. mkey.add((String) entry.getKey());
  18. mvalue.add((String) entry.getValue());
  19. }
  20. sheet.setDefaultColumnWidth((short) 12);
  21. HSSFCell cell = null;
  22. for (int i = 0;i<mvalue.size();i++) {
  23. cell = getCell(sheet, 0, i);
  24. setText(cell, mvalue.get(i));
  25. }
  26.  
  27. for (short i = 0; i < contentList.size(); i++) {
  28. HSSFRow sheetRow = sheet.createRow(i+1);
  29. Map<String, Object> entity = contentList.get(i);
  30. for (int j = 0;j< mkey.size();j++) {
  31. if (entity.get(mkey.get(j)) instanceof String) {
  32. sheetRow.createCell(j).setCellValue((String)entity.get(mkey.get(j)));
  33. } else if (entity.get(mkey.get(j)) instanceof Double) {
  34. sheetRow.createCell(j).setCellValue((Double)entity.get(mkey.get(j)));
  35. } else if (entity.get(mkey.get(j)) instanceof Date){
  36. String date = (entity.get(mkey.get(j))).toString();
  37. sheetRow.createCell(j).setCellValue(date.substring(0, 10));
  38. } else if (entity.get(mkey.get(j)) instanceof BigDecimal){
  39. sheetRow.createCell(j).setCellValue((entity.get(mkey.get(j))).toString());
  40. }
  41. }
  42. }
  43. }
  44. } else if ("2".equals(type)) {
  45. List<String[]> contentList = (List<String[]>) obj.get("content");
  46. HSSFSheet sheet = workbook.createSheet("sheet1");
  47. String[] titleList = (String[]) obj.get("title");
  48. HSSFCell cell = null;
  49. for (int i = 0;i<titleList.length;i++) {
  50. cell = getCell(sheet, 0, i);
  51. setText(cell, titleList[i]);
  52. }
  53. for (short i = 0; i < contentList.size(); i++) {
  54. HSSFRow sheetRow = sheet.createRow(i+1);
  55. String[] detail = contentList.get(i);
  56. for (int j = 0;j< detail.length;j++) {
  57. sheetRow.createCell(j).setCellValue((String)contentList.get(i)[j]);
  58. }
  59. }
  60. }
  61.  
  62. //设置下载时客户端Excel的名称
  63. String filename = fileName + ".xls";
  64. //处理中文文件名
  65. filename = Chineseutil.encodeFilename(filename, request);
  66. response.setContentType("application/Vnd.ms-excel;charset=UTF-8");
  67. response.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("gb2312"), "iso8859-1"));
  68. OutputStream ouputStream = response.getOutputStream();
  69. workbook.write(ouputStream);
  70.  
  71. //导出数据后将信息存入cookie
  72. Cookie status = new Cookie("updtstatus", "1");
  73. status.setMaxAge(3600);//设置cookie存活时间1个小时
  74. response.addCookie(status);
  75.  
  76. ouputStream.flush();
  77. ouputStream.close();
  78. }

Java 导出Excel的各种尝试的更多相关文章

  1. java导出excel报错:getOutputStream() has already been called for this response

    对于java导出excel报错的问题,查了很多都说是在使用完输出流以后调用以下两行代码即可 out.clear(); out = pageContext.pushBody(); 但这也许是页面上输出时 ...

  2. java导出excel表格

    java导出excel表格: 1.导入jar包 <dependency> <groupId>org.apache.poi</groupId> <artifac ...

  3. java导出excel报表

    1.java导出excel报表: package cn.jcenterhome.util; import java.io.OutputStream;import java.util.List;impo ...

  4. Java导出Excel和CSV(简单Demo)

    Java导出Excel和CSV的简单实现,分别使用POI和JavaCSV. JavaBean public class ReportInfo { int id; String date; int nu ...

  5. Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类

    Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类 ============================== ©Copyright 蕃薯耀 20 ...

  6. java导出excel模板数据

    Java导出excel数据模板,这里直接贴代码开发,流程性的走下去就是步骤: String[] colName=new String[]{"期间","科目代码" ...

  7. java导出excel工具类

    java导出excel须要使用HSSFWorkbook这个类,须要导入poi-3.6-20091214.jar 工具类调用例如以下: package com.qlwb.business.util; i ...

  8. [转载]Java导出Excel

    一.需求介绍 当前B/S模式已成为应用开发的主流,而在开发企业办公系统的过程中,常常有客户这样子要求:把系统数据库中的数据导出到Excel,用户查看报表时直接用Excel打开.或者是:用户已经习惯用E ...

  9. Java导出excel

    一.介绍 常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统.银行系统).或者是:我们已经习惯用Excel打印.这样在我们实际的开发中,很多时候需要实现导入.导出Excel的应用. ...

随机推荐

  1. reactor 类库,基于事件编程

    https://github.com/reactor https://github.com/reactor/reactor-samples/ https://github.com/ReactiveX/ ...

  2. USACO 1.3.2

    题目链接:USACO 1.3.2 这道题有点小坑,不是算法错了,而是文件名,是barn1不是barnl,恕我眼拙,找了十五分钟... 肯定是木板的个数用的越多越好,这样可以减少空隙. 简单的贪心,将每 ...

  3. mysql查询的cache

    Mysql SQL_NO_CACHE不生效的问题 贾春春 1 票 1224 我想通过SQL_NO_CACHE得知某个query查询速度,但似乎无法实现 例如首次查询: mysql> select ...

  4. gnome3 no launcher

    http://askubuntu.com/questions/43246/how-to-configure-gnome-3-to-show-icons-on-desktop http://superu ...

  5. Mysql基于GTID主从复制

    Mysql5.6基于GTID全局事务的复制 什么是GTID?   GTID(Global Transaction Identifiers)是全局事务标识 当使用GTIDS时,在主上提交的每一个事务都会 ...

  6. ibatis一对多 数据库设计及实现

    iBatis的多表关联. ibatis的表关联,和数据库语句无关,是在Java程序中,把若干语句的结果关联到一起.这种关联形式,虽然在大数据量时是很奢侈的行为,但是看起来很干净,用起来也很方便. 这里 ...

  7. 前台html与后台php通信(上传文件)

    这部分为导入txt文本文件,存放在服务器然后返回txt文本的内容到前台进行相应操作 前台html代码 <div id="coordinate_div">         ...

  8. CentOS 6.4 利用 Awstats 7.2 分析 Nginx 日志

    一.配置Nginx 日志分割 (略) 二.配置FCGI 1.安装CPAN wget http://search.cpan.org/CPAN/authors/id/A/AN/ANDK/CPAN-2.00 ...

  9. heritrix1.14.4配置-没有add和change按钮的问题

    今天搞了下heritrix1.14.4在eclipse下的配置,根据http://www.360doc.com/content/10/0913/18/2793979_53385587.shtml教程, ...

  10. 【python】matplotlib在windows下安装

    昨晚装了好久的这玩意,终于在凌晨成功搞定,然后跑起了一个人人网抓取好友关系的脚本~开心. 以下是我参考的最给力的文档,全部安装一遍,就可以啦~ 但是!在安装前一定要先确认自己的python版本!本人自 ...