大家好呀,最近工作中遇到的问题,给大家做一个分享和记录。截止到九月开学,我还是一个大三的学生,所以呢,我目前还是一个练习时长一个月的开发实习生。很幸运,我到的项目组是使用开源框架开发的,就是vue + Spring Boot,我其他实习生同事被分到了老项目,还是jsp、servlet哪些东西,还会在页面里面写Java代码,确实有点……
虽然用到了 vue + Spring Boot ,但是呢全是用的公司的框架,就像vue,平时查看用法去vue.js官网看就行,我们公司呢,也有一个官网,上面是前端框架用法,当然呢,这个网站没有发布,得连公司内网才能访问。跟vue用法一样,有vue基础几乎都能看懂“大致意思”,看懂归看懂,自己想写还得多努力几天的哈;还有那个Spring Boot也是不常规的,就是跟我们平时在学校和在网课上看的不一样,也是公司框架┭┮﹏┭┮,有基础的话,多努力努力,做个增删改查还是上手很快的O(∩_∩)O,希望让一些还没有去工作的牛牛有一定的了解。多学习一下:SQL 、VUE 、Spring Boot ,当然为了过面试那关,还得多学习一些其他知识的。
(注:我是一个学后端的,但是来公司了,前后端都得写,毕竟是个搞web开发的,Html和css不可能一点不会,但是……懂得都懂┭┮﹏┭┮)
好的,正文开始(源码在最后):
目的是要用vue和后台做一个下载功能,我们平时前端调用后端一般都是使用axios,但是axios无法实现下载功能,所以我想到了,原生js,当然axios也有解决方法,大家可以自行百度了解。
下载Excel表格,后端呢,我知道两种方法:阿里的EasyExcel ,和阿帕奇的poi
easyExcel官网:https://www.yuque.com/easyexcel/doc/easyexcel (汉化,易懂)
里面有文件下载的例子,我就不粘过来了
poi : https://poi.apache.org/components/spreadsheet/quick-guide.html#ReadWriteWorkbook
其实下载功能我们都是用的:esponse中的OutputStream进行文件下载
一个下载小例子:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用response获得字节输出流 ServletOutputStream out=response.getOutputStream(); //获得服务器上面的图片 String realpath=this.getServletContext().getRealPath("456.png"); InputStream in=new FileInputStream(realpath); int len=0; byte[] buffer=new byte[1024]; while((len=in.read(buffer))>0){ out.write(buffer,0,len); } in.close(); out.close(); }
下面就是我的源码,两种都有,注解详细:
easyexcel不要忘记,实体类哟,根据实体类上注解生成表格列名:
public class User extends BaseRowModel { // 主键id @ExcelIgnore // 生成报表时忽略,不生成次字段 private Integer id; @ExcelProperty(value = "姓名", index = 0) // 定义表头名称和位置,0代表第一列 private String name; @ExcelProperty(value = "年龄", index = 1) private Integer age; @ColumnWidth(20) // 定义列宽 @DateTimeFormat(value = "yyyy/MM/dd") @ExcelProperty(value = "出生日期", index = 2) private Date birthday; }
/*easyExcel导出*/ @RequestMapping(value = "/exportExcel") public void exportExcel(HttpServletResponse response) throws IOException { //设置编码与文件类型 response.setContentType("mutipart/form-data"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-disposition","attachment;filename=test.xlsx"); ServletOutputStream out=response.getOutputStream(); //导出的数据 List<User> users = userService.findAll(); //导出并下载 EasyExcel.write(out,User.class).sheet("test").doWrite(users); out.flush(); out.close(); }
poi:
//poi生成xls文件并下载 @GetMapping("/download") public void download(HttpServletResponse response){ response.setContentType("application/binary;charset=UTF-8"); try{ ServletOutputStream out=response.getOutputStream(); //文件名 String name = "扫描榜单下载"; try { //设置文件头:最后一个参数是设置下载文件名 response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(name+".xls", "UTF-8")); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } //表格的列的标题 String[] titles = { "姓名","年龄","出生日期" }; //表格的数据,这里是查询,因为是例子,我做的查询全部,可自定义 List<User> tops = userService.findAll(); export(tops,titles, out); } catch(Exception e){ e.printStackTrace(); } } //转成.xls文件 public void export(List<User> tops,String[] titles, ServletOutputStream out) throws Exception{ try{ // 第一步,创建一个workbook,对应一个Excel文件 HSSFWorkbook workbook = new HSSFWorkbook(); //表名 String sheetName="扫描榜单"; // 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet HSSFSheet hssfSheet = workbook.createSheet(sheetName); // 第三步,在sheet中添加表头第0行(表头),注意老版本poi对Excel的行数列数有限制short HSSFRow row = hssfSheet.createRow(0); // 第四步,创建单元格,并设置值表头 设置表头居中 HSSFCellStyle hssfCellStyle = workbook.createCellStyle(); //居中样式 hssfCellStyle.setAlignment(HorizontalAlignment.CENTER); //创建列 HSSFCell hssfCell = null; for (int i = 0; i < titles.length; i++) { hssfCell = row.createCell(i);//列索引从0开始 hssfCell.setCellValue(titles[i]);//列名1 hssfCell.setCellStyle(hssfCellStyle);//列居中显示 } /*把要导入的值放到一个二维数组中,表格正好对应二维数组*/ String[][] dataList =new String[tops.size()][3]; //将日期类型转换成字符串类型 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); for(int i=0;i<tops.size();i++){ dataList[i][0]=tops.get(i).getName(); dataList[i][1]=String.valueOf(tops.get(i).getAge()); //日期类型格式化成字符型 dataList[i][2]=sdf.format(tops.get(i).getBirthday()); } //把表格内容加入,从第二行开始 for(int i=0;i<dataList.length;i++){ row=hssfSheet.createRow(i+1); for(int j=0;j<3;j++){ row.createCell(j).setCellValue(dataList[i][j]); } } // 第七步,将文件输出到客户端浏览器 try { workbook.write(out); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } }catch(Exception e){ e.printStackTrace(); throw new Exception("导出信息失败!"); } }
当然第一步都是先导依赖哈
<!--导出导入easyexcel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.4</version> </dependency> <!-- org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency>
然后就是原生js发送post请求:
<button onclick="send()">测试</button> <script> function post(url, params) { var temp = document.createElement("form"); temp.action = url; temp.method = "post"; temp.style.display = "none"; for ( var x in params) { var opt = document.createElement("input"); opt.name = x; opt.value = params[x]; temp.appendChild(opt); } document.body.appendChild(temp); temp.submit(); return temp; } //调用post方法,发送请求,只是例子,age写死了 function send() { post( "http://127.0.0.1:8080/user/download", { age : 23 }); } </script>
AJAX无法下载文件的原因
下载其实是浏览器的内置事件,浏览器的 GET请求(frame、a)、 POST请求(form)具有如下特点:
response会交由浏览器处理
response内容可以为二进制文件、字符串等
但是AJAX请求不一样:
response会交由 Javascript 处理
response内容只能接收字符串才能继续处理
因此,AJAX本身无法触发浏览器的下载功能。
最后在vue中整合:
//下载,调用post请求 download() { this.post({ pageNumber: this.pageNumber, pageSize: this.pageSize, sonarState: this.appState, appName: this.searchContent, roleName: this.roleName }); }, //发送post请求 post( params){ var form = document.createElement("form"); form.style.display = "none"; form.action = 'http://localhost:8090/download'; form.method = "post"; document.body.appendChild(form); for (var key in params) { var input = document.createElement("input"); input.type = "hidden"; input.name = key; input.value = params[key]; form.appendChild(input); } form.submit(); form.remove(); return form; },
后台demo下载:
链接:https://pan.baidu.com/s/1lGlE1qrN7oFSlbDsfCtBRQ
提取码:o0ud