javaweb后端之Spring+HttpServletResponse+WritableWorkbook實現網頁下載excel


代碼渣渣一枚,最近在實習(主要是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就意味着網頁一定會彈出下載的對話框,哪怕文件名和文件路徑都不存在。

結束語:

第一次寫博客,寫的不好大家多多見諒,同時也希望自己能夠堅持下去。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM