获取jqGrid中的所有数据导出并生成Excel文件流供用户下载(post请求实现文件下载)

最近有一个需求是:

将jqGrid表格中的数据生成报表Excel文件返回给用户。

我的想法是获取jqGrid中的数据然后生成json数据,传给后端,生成文件流,响应到前端,保存为excel文件。

ajax为什么不能够实现下载文件

ajax的返回值类型是json,text,html,xml类型,或者可以说ajax的接收类型只能是string字符串,不是流类型,所以无法实现文件下载。

但用ajax仍然可以获得文件的内容,该文件将被保留在内存中,无法将文件保存到磁盘。这是因为JavaScript无法和磁盘进行交互,否则这会是一个严重的安全问题,js无法调用到浏览器的下载处理机制和程序,会被浏览器阻塞。

并且 我用ajax实现的时候出现了很多bug。

在网上参考好多博客,经过不断的调试,我还是选择了原生的XMLHttpRequest对象进行post请求。

blob(HTML5 新特性)

二进制大对象,是一个可以存储二进制文件的容器。

作用

Js一直以来都没有比较好的可以直接处理二进制的方法。而Blob的存在,允许我们可以通过JS直接操作二进制数据。

Blob对象可以看做是存放二进制数据的容器,此外还可以通过Blob设置二进制数据的MIME类型。

BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,由于它们的尺寸,必须使用特殊的方式来处理(例如:上传、下载或者存放到一个数据库)。

重点应用

目前做的通过URL下载文件。

分片上传文件(将大文件分片,轮询向后台提交各文件片段)。

后端代码 /** * 生成Excel报表 * Error:存在问题 * 1. 前端表格中没有Student对象的一些属性,生成报表时不必要显示的属性字段在Excel中显示。 * solve:加判断控制。 * 2. (由于blob是HTML5新出的)兼容性问题:chrome、firefox、opera无问题, * 3. 检测grid表格中有无字段名称冲突问题。 * solve:细心检查即可 * 4. 下载完Excel,打开出现"文件已损坏 无法打开"问题,这是因为office受保护试图导致(安全问题) * solve:在office选项里边修改一下即可(客户端问题) * @param list * @param response */ @RequestMapping(value = "/exstudent",consumes = "application/json;charset=utf-8") public void export (@RequestBody List<Student> list, HttpServletResponse response){ OutputStream out = null; String name = "学生信息管理表"; for (Student stu:list) { System.out.println(stu.getStudentname()); } try { response.setHeader("content-type", "application/octet-stream"); response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=" +URLEncoder.encode(name, "UTF-8")+".xlsx"); out = response.getOutputStream(); //调用老师自己写的库,本篇文章不详细说生成Excel文件的事情。 TExcel.exportExcel(name,Student.class,list,out); System.out.println("下载ok"); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); }finally{ } } 前端代码: //导出按钮被点击之后,将按钮制为无效(防止多次生成) function abideBtn(){ console.log("禁止按钮......"); $("#download").attr({"href":"#"}); $("#download").css("cursor","not-allowed"); } //下载过程中出错误, function downloadError(){ console.log("发生错误,下载失败"); alert("下载中出现错误!请重试"); $("#download").attr({"href":"javascript:exportData();"}); $("#download").css("cursor","pointer"); } //导出表格数据 //注意:下面获取jqGrid中所有行数据的前提是分页在前端,而不是后端。 //如果你是在后端分页,那么你会发现,你会将所有数据都显示出来。 function exportData() { var grid = jQuery("#grid"); //获取当前显示的数据 var rowNum = grid.jqGrid(\'getGridParam\', \'rowNum\'); //获取显示配置记录数量 var total = grid.jqGrid(\'getGridParam\', \'records\'); //获取查询得到的总记录数量 //设置rowNum为总记录数量并且刷新jqGrid,使所有记录现出来调用getRowData方法才能获取到所有数据 grid.jqGrid(\'setGridParam\',{rowNum: total,}).trigger(\'reloadGrid\'); var rows = o.jqGrid(\'getRowData\'); grid.jqGrid(\'setGridParam\',{rowNum: rowNum,}).trigger(\'reloadGrid\'); postToPOM(rows); } //发送post请求 function postToPOM(rows) { console.log(rows); var url = "../student/exstudent"; var xhr = new XMLHttpRequest(); xhr.open(\'POST\',url,true); xhr.responseType = "blob"; xhr.setRequestHeader("Content-Type" , "application/json;charset=utf-8"); //添加监听事件。 xhr.addEventListener("load",abideBtn,false); xhr.addEventListener("error",downloadError,false); xhr.onload = function (){ if(this.status === 200){ //创建Bolb对象 var blob = this.response;//html5新出的 var reader = new FileReader(); reader.readAsDataURL(blob); reader.onload = function(e){ //创建a标签,构造下载弹窗 var a = document.createElement("a"); a.id = "downloadTag"; a.download = \'学生信息管理表.xlsx\'; a.href = e.target.result; $("body").append(a); a.click(); $("#downloadTag").remove(); console.log("下载完成!"); //恢复按钮 $("#download").attr({"href":"javascript:exportData();"}); $("#download").css("cursor","pointer"); } } }; xhr.send(JSON.stringify(rows)); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzsgzd.html