javaweb后端之Spring+HttpServletResponse+WritableWorkbook实现网页下载excel

时间:2024-02-21 07:43:07

代码渣渣一枚,最近在实习(主要是javaweb后端),在实习期间,写了一点网页下载excel表格的代码,趁着现在对他还有印象,记录下来,方便以后用。第一次写博客,一定会很差,各位看官不要见怪!!废话就不多说了,下面正式开始介绍。

实现功能:网页点击下载,将参数传到后端,根据参数查询数据库,将查到的数据导入excel表,并返回前端下载。

实现上述功能大体分为以下几步:

一.查询数据库

这部分用spring框架实现,代码十分简单,不再赘述。由于我的功能实现中查询到的数据很多条,因此将查询到的数据封装到ArrayList中,ArrayList中的元素是预先定义好的bean。

二.生成excel

 这部分用的是jxl的WritableWorkbook生成excel,网上说poi也可以,查了一下,各有优缺点,poi效率高,但当写入大量数据时,消耗内存大。用WritableWorkbook生成excel表格主要分为以下几步:

1.从配置文件中读取path和filename

这样做的好处是当要更改excel文件的存放地址,直接在配置文件中更改,不用改动程序。另外,path和filename最好不好出现中文,避免乱码,同时也显得更加专业。据说出现中文会被批不专业甚至被boss骂。

另外,path=配置文件中读取的固定路径+程序中年月日生成的可变路径,这样做的好处是每天生成一个文件夹,用于存放今天下载的excel表格。方便管理和查找,同时也避免了大量的excel表格都存放在同一个文件夹中,增加查找困难。同理,为了区分不同的将要下载的excel表,filename=配置文件中读取的固定exccel文件名+程序中小时分钟生成的可变文件名+“.xls”,这样做可以使同一天内的excel文件名保持不相同。

生成年月日的可变路径的代码如下:

java代码

1 public static String getRelativeDir() {
2     //Date d = new Date(); 
3     Calendar calendar = Calendar.getInstance();  
4     SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd");
5     String curDate = s.format(calendar.getTime());  //当前日期
6     return curDate;
7     }

生成小时分钟的可变文件名的代码如下:

java代码

 1 public static String hourMinuteStr() {
 2     Calendar cal = Calendar.getInstance();
 3     //当前小时数
 4     int time = cal.get(Calendar.HOUR_OF_DAY);      
 5     // 当前分钟数  
 6     int MINUTE = cal.get(Calendar.MINUTE);  
 7     String randomnum = time+""+MINUTE;
 8     //如果月份为7转变为07
 9     return randomnum.length()==3?"0"+randomnum:randomnum;
10  }

2.创建WritableWorkbook

在生成path和filenme后,就可以创建一个WritableWorkbook生成excel

java代码 

1 //以file为文件名来创建一个Workbook
2 File file = new File(path+"/"+filename);
3 WritableWorkbook wwb = Workbook.createWorkbook(file);
4 // 创建工作表
5 WritableSheet ws = wwb.createSheet("Test Shee 1", 0);

3.设置excel表的格式

如果不设置excel表的格式,excel将使用默认的格式。在最初,我并没有设置excel表格的格式,然后发现excel表格不美观,因此添加了设置excel表格格式的代码。

java代码

 1 //给sheet电子版中所有的列设置默认的列的宽度;  
 2 ws.getSettings().setDefaultColumnWidth(10);  
 3 //给某一列设置特殊的宽度
 4 ws.setColumnView(4, 20); 
 5 //设置字体;  
 6 WritableFont font1 = new WritableFont(WritableFont.ARIAL,9,WritableFont.BOLD,false,UnderlineStyle.NO_UNDERLINE,Colour.BLACK); 
 7 WritableCellFormat cellFormat1 = new WritableCellFormat(font1);
 8 //设置文字居中对齐方式;                  cellFormat1.setAlignment(jxl.format.Alignment.CENTRE);  
 9 // 设置边框线 
10 cellFormat1.setBorder(Border.ALL, BorderLineStyle.THIN); 
11 //设置背景颜色                    
12 cellFormat1.setBackground(jxl.format.Colour.YELLOW);
13 //设置自动换行;  
14 cellFormat1.setWrap(true);  
15 //设置垂直居中;              
16 cellFormat1.setVerticalAlignment(VerticalAlignment.CENTRE);  

4.生成excel表中的lable

设置了excel表格的样式后,就可以生成excel表格的元素了

java代码

1 //要插入到的Excel表格的列号,默认从0开始
2 Label label_serilaNum= new Label(0, 0, "序号",cellFormat1);
3 //表示第1行第2列的值
4 Label label_createdBy= new Label(1, 0, "负责人",cellFormat1);
5 Label label_province= new Label(2, 0, "区域",cellFormat1);
6 ws.addCell(label_serilaNum);
7 ws.addCell(label_createdBy);
8 ws.addCell(label_province);

如果不需要设置excel表的格式,在new Lable中去掉cellFormat1就可以了,这样excel会选择默认的格式

我们上面说到,从数据库中查到的信息是存放在ArrayList中,上面的代码只是生成了表格的标题行,ArrayList中存储的信息并没有添加到excel表格中,添加ArrayList中的信息到excel表格中,只需要遍历ArrayList,像上面的代码一样,将ArrayList中的信息填写在对应的label中就可以了。注意判断ArrayList是否为null,否者系统会抛出错误

5.写/关文档

在将ArrayList中的信息写入excel后,还需要完成以下两步

java代码

1 //写进文档
2 wwb.write();
3 // 关闭Excel工作簿对象
4 wwb.close();

三.将生成的excel表格的文件路径和文件名返回给前端

在上述excel文件生成后,将文件的路径和文件名返回给前端,这就完成了网页下载表格的一大半。另外需要注意的是,返回的路径最好不要是绝对路径,应该为相对路径。此处返回的路径=“/”+程序生成的年月日可变文件夹;这样做的好处是下载请求端不知道存放文件的具体位置,确保了文件的安全。

四.网页弹出下载excel文件的对话框

实现网页下载excel还需要最后一步:接收参数filename和filepath,这两个参数是第三步中传给前端的文件路径(相对)和文件名,为什么要如此麻烦,后端直接下载不更加简洁?这是因为这样可以确保当前用户还是发出下载请求的用户,而不是其他的用户;另外还可以再次确认下载的excel是哪一个。

1.检查文件路径和文件名称是否存在

在接收到前端传来的filename和filepath时,第一步做的是检测文件路径和文件名称是否存在,如果存在才进行下一步的下载,否则不下载。

java代码

 1 //检查文件路径
 2 BaseResponse baseResponse = new BaseResponse();
 3 String loadDir=loadDir_prefix+filepath;
 4 File exceldir=new File(loadDir);
 5 if(!exceldir.isDirectory()) {
 6     baseResponse.setMsg("待下载的文件路径不对,请输入正确的路径");
 7     baseResponse.setCode(ResponseCode.PARAMETER_ERROR);
 8     return baseResponse;
 9 }
10 //检查文件
11 String path=loadDir+"/"+filename;
12 File file = new File(path);
13 if(!file.exists()) {
14     baseResponse.setMsg("待下载的文件不存在,请输入正确的文件名");
15     baseResponse.setCode(ResponseCode.PARAMETER_ERROR);
16     return baseResponse;
17 }

注意:前端传回的路径是相对路径(由年月日生成的文件夹),这样做的好处前面已经提到了。

2.使用HttpServletResponse下载excel文件

文件路径和文件检查通过后,使用HttpServletResponse下载文件

 1 String filenametemp=filename.substring(filename.length()-8, filename.length()-4);
 2 //设置excel文件名
 3 response.setHeader("Content-Disposition", "attachment; filename=" +URLEncoder.encode("eSIM芯片管理平台消息预警查询及导出", "utf-8")+ "["+URLEncoder.encode("表样","utf-8")+"]"+filenametemp+".xls");
 4 //4.获取要下载的文件输入流
 5 InputStream in = new FileInputStream(new File(filepath+"/"+filename));
 6 int len = 0;
 7 //5.创建数据缓冲区
 8 byte[] buffer = new byte[1024];
 9 //6.通过response对象获取OutputStream流
10 OutputStream out = response.getOutputStream();
11 //7.将FileInputStream流写入到buffer缓冲区
12 while ((len = in.read(buffer)) > 0) {
13     //8.使用OutputStream将缓冲区的数据输出到客户端浏览器
14     out.write(buffer,0,len);
15     }
16 in.close();
17 out.flush();
18 response.flushBuffer();//不可少
19 out.close();
20     }  

上诉代码中的filenametemp是获取的由小时分钟生成的相对文件名。另外上诉也提到了,excel的文件名是英文,但在response.setHeader中设置的文件名与传到前端的文件名不相同,这样做是没有问题的。response.setHeader参数中的文件名才是excel最后的下载名,之前叫什么完全没有关系。对于response.setHeader中的filename还有一点需要注意的是如果文件名是中文,需要utf-8进行编码,否则会出现乱码,特殊字符(如[ ] @等)不能进行utf-8编码,编码反而会导致出现乱码,直接将特殊字符添加在文件中就可以了。

最后的最后,response.setHeader要在检查文件路径和文件名之后再进行设置,因为一旦设置response.setHeader就意味着网页一定会弹出下载的对话框,哪怕文件名和文件路径都不存在。

结束语:

第一次写博客,写的不好大家多多见谅,同时也希望自己能够坚持下去。