java实现异步导出数据
程序员文章站
2022-03-16 21:38:29
问题概述:使用java作为后台语言,用poi导出数据时无法异步导出,当数据量稍微大点,就会出现页面傻瓜式等待 (点击导出后,页面无任何反应和提示,还以为此功能无效。然则几秒后浏览器才响应。)这样体验非...
问题概述:
使用java作为后台语言,用poi导出数据时无法异步导出,当数据量稍微大点,就会出现页面傻瓜式等待 (点击导出后,页面无任何反应和提示,还以为此功能无效。然则几秒后浏览器才响应。)这样体验非常 不好。
解决办法:
很简单,将下载数据分离为一个单独方法。在触发导出后,先获取并封装数据(数据量大的话这个过程正好给页面做一个等待框,提示正在下载数据),完成后给前台返回一个状态,当前台收到返回正确返回状态后再关闭等待框并调用下载方法。
demo:
1、获取并封装数据
@requestmapping("exportexcel") //用户数据导出 public void exportexcel(httpservletrequest request, httpservletresponse response) { map<string,object> map = new hashmap<string,object>(); try{ equipmentaccident search=(equipmentaccident) request.getsession().getattribute("equipmentaccident1"); //获取保存在session中的查询条件 if(search !=null ){ if(str.isnotnull(search.getname())){ //名称 map.put("name", search.getname()); } if(str.isnotnull(search.getremark())){ //备注 map.put("remark", search.getremark()); } } list<user> list=userservice.selectexcel(map); //查询数据 xssfworkbook wb = new xssfworkbook(); // 声明一个工作薄 xssfsheet sheet = wb.createsheet("用户信息"); // 生成一个表格 integer columnindex = 0; sheet.setcolumnwidth(columnindex++, 3 * 512); // 设置表格第一列宽度为3个字节 sheet.setcolumnwidth(columnindex++, 10 * 512); //名称 sheet.setcolumnwidth(columnindex++, 10 * 512); //年龄 sheet.setcolumnwidth(columnindex++, 10 * 512); //备注 // 生成一个样式 xssfcellstyle style1 = wb.createcellstyle(); // 设置这些样式 style1.setfillforegroundcolor(indexedcolors.grey_25_percent.getindex()); // 生成一个字体 xssffont font1 = wb.createfont(); font1.setfontheightinpoints((short) 11); font1.setfontname("黑体"); // 字体 // 把字体应用到当前的样式 style1.setfont(font1); //在sheet里增加合并单元格 cellrangeaddress cra = new cellrangeaddress(0, 0, 0, 7); sheet.addmergedregion(cra); int rowint = 0; //列号 xssfrow row = sheet.createrow(rowint++); xssfcell cell = row.createcell(0); cell.setcellstyle(style1); cell.setcellvalue("用户信息"); int cellint = 0; row = sheet.createrow(rowint++); cell = row.createcell(cellint++); cell.setcellstyle(style1); cell.setcellvalue("序号"); cell = row.createcell(cellint++); cell.setcellstyle(style1); cell.setcellvalue("名称"); cell = row.createcell(cellint++); cell.setcellstyle(style1); cell.setcellvalue("年龄"); cell = row.createcell(cellint++); cell.setcellstyle(style1); cell.setcellvalue("备注"); int index = 0; if(list!=null && !list.isempty()){ for(user obj:list){ index++; cellint = 0; row = sheet.createrow(rowint++); cell = row.createcell(cellint++); cell.setcellvalue(index); cell = row.createcell(cellint++); cell.setcellvalue(obj.getname()); cell = row.createcell(cellint++); cell.setcellvalue(obj.getage()); cell = row.createcell(cellint++); cell.setcellvalue(obj.getremark()); } } //反馈给前台状态 response.getwriter().append("ok"); //xssfworkbook对象保持到session里,供下载使用 request.getsession().setattribute("xssfworkbook",wb); } catch (exception e) { e.printstacktrace(); } }
2、分离出来的下载方法
/** * @param filename 下载文件名称 * @param request 请求对象 * @param response 响应对象 * 2020-11-10 新增 */ @requestmapping("downloadexcel") public void downloadexcel(string filename,httpservletrequest request,httpservletresponse response) { if(str.isnotnull(filename)){ user loginuser = (user) request.getsession().getattribute("loginuser"); //检验下载路径并返回url string url = filetool.getdownloadurl(loginuser, filename, request); //从url里截取出文件全名 filename = url.substring(url.lastindexof("/")+1); //创建文件输出流 fileoutputstream fileout = null; try { fileout = new fileoutputstream(url); //获取保存在session中的待下载数据 xssfworkbook wb = (xssfworkbook) request.getsession().getattribute("xssfworkbook"); wb.write(fileout); } catch (filenotfoundexception e) { e.printstacktrace(); }catch (ioexception e) { e.printstacktrace(); } finally{ if(fileout != null){ try { fileout.close(); } catch (ioexception e) { e.printstacktrace(); } } } try { system.out.println("------------开始下载文件---------------"); file file = new file(url); // 以流的形式下载文件。 inputstream fis = new bufferedinputstream(new fileinputstream(url)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); // 清空response response.reset(); // 设置response的header response.addheader("content-disposition", "attachment;filename=" + new string(filename.getbytes("utf-8"), "iso8859-1")); response.addheader("content-length", "" + file.length()); outputstream toclient = new bufferedoutputstream(response.getoutputstream()); response.setcontenttype("application/octet-stream"); toclient.write(buffer); toclient.flush(); toclient.close(); //清除session里的数据 request.getsession().removeattribute("xssfworkbook"); } catch (ioexception ex) { ex.printstacktrace(); } } }
3、前台调用导出数据
//导出请求 function exportexcel(){ var load = saveload("导出中,请稍后...",1); //打开一个等待框 $.ajax({ type: "post", url: "exportexcel", datatype:"text", error: function(request) { closesaveload(load,1); return false; }, success: function(msg) { if(msg=='ok'){ closesaveload(load,1); //关闭等待框 //下载请求地址 window.location.href="downloadexcel?filename=用户信息" rel="external nofollow" ; }else{ closesaveload(load,1); //关闭等待框 layer.msg("导出失败,刷新页面重试",{icon:2}); return false; } } }); }
效果如下:
总结:
以前是将封装数据和下载数据放一个方法里面,导致下载需要等待很久,而等待的时候,无法提示用户后台正在处理数据。将数据和下载分开后就可以达到等待时提示,加载完下载。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。