天天看點

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就意味着網頁一定會彈出下載下傳的對話框,哪怕檔案名和檔案路徑都不存在。

結束語:

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