理解和靈活應用 Struts2 的文件下載功能

文件下載給我們最直接的概念就是,給個文件鏈接點擊就下載。似乎太簡單,然而 Struts2 卻把它作爲一個獨立的學問來對待,理由有四: 1. 文件名爲中文時,直接點擊下載,鏈接可能會走樣(某些瀏覽器,URL 編碼的問題),致使無法下載。 2. 不總是從下載實際的文件,文件內容有時候是動態生成的,如數據庫中的內容。 3. 對於知名的文件類型不讓瀏覽器直接打開,而是出現下載對話框保存文件。例如,要下載的文件是 .txt 的,可能直接就在瀏覽器中顯示其內容。 4. 需要授權才能下載文件時 當然對於以上若干問題,Servlet/JSP 都能通過正確的 URL 編碼,響應頭設置、權限代碼控制解決,只是 Struts2 讓我們處理起來更方便了,內部原理自然是一樣的。 先來看下 Servlet 如何實現文件下載的,直接見代碼: view sourceprint?01.PrintWriter out = response.getWriter(); 02. 03.//不管實際類型,待下載文件 ContentType 統一指定爲 application/octet-stream 04.response.setContentType("application/octet-stream"); 05. 06.//中文文件名必須轉碼爲 ISO8859-1,否則爲亂碼 07.String fileName = new String("文本文件.txt".getBytes(), "ISO8859-1"); 08. 09.//作爲附件下載,相應的 "inline;filename = "+fileName 是在線(瀏覽器中顯示內容)打開 10.response.setHeader("Content-Disposition", "attachment;filename=" + fileName); 11. 12.//因爲文件編碼也爲 ISO8859-1,所以內容須轉碼成 ISO8859-1,尚不知如何控制下載文本文件的編碼 13.//或有誰知道的,還請告訴我一下。 文件內容可以從物理文件中來,或者數據庫中讀取填入等等 14.out.write(new String("Servlet 文件下載測試".getBytes(), "ISO8859-1")); 15. 16.out.close(); 知道了上面各行的含義,再來看下 Struts2 的解決方式,其實不過是把某些代碼的功能移入到了配置文件而已。在李剛所著的《Struts 2 權威指南》中說 Struts 實現文件下載是由一個 download 攔截器。其實不然,只是一個 StreamResult(org.apache.struts2.dispatcher.StreamResult) 而已,也不像實現文件上傳那樣要額外的 JAR 包。在 StreamResult 中有以下幾個默認屬性要留意一下: public static final String DEFAULT_PARAM = "inputName"; protected String contentType = "text/plain"; protected String contentDisposition = "inline"; protected String inputName = "inputStream"; protected InputStream inputStream; protected int bufferSize = 1024; StreamResult 的實現細節敬請閱讀它的源代碼,實現過程一言以蔽之就是:從 inputStream 獲取內容,以相應的 contentType、contentDisposition 和 bufferSize 輸出給瀏覽器,對 contentType 和 contentDisposition 的相應設置就能實現文件下載,可對照前面 Servlet 的實現。看個實際的例子吧。 struts.xml 中 Action 的配置,假定 Action 類爲 com.unmi.DownLoadAction view sourceprint?01. 02. 03. application/octet-stream 04. 05. 07. inputStream 08. 09. 12. attachment;filename="${fileName}" 13. 4096 14. 說明:對於上面的配置其他參數可以用默認值,關鍵就是 contentDisposition 要設置爲 attachment 才能提示下載,同時用 filename 指定文件名,若直接指定非動態的文件名。 DownloadAction 代碼,需要實現 getInputStream() 返回輸入流;因前面用的動態文件名,所以須加上 getFileName() 返回文件名,若非動態文件名,則該方法可省去。 view sourceprint?01.package com.unmi.action; 02. 03.import java.io.*; 04.import java.text.*; 05.import java.util.Date; 06. 07./** 08. * 文件下載的 Action 09. * @author Unmi 10. */ 11.public class NetbookSerialAction { 12. 13. public String execute() throws Exception { 14. //這裏可加入權限控制 15. return "success"; 16. } 17. 18. //獲得下載文件的內容,可以直接讀入一個物理文件或從數據庫中獲取內容 19. public InputStream getInputStream() throws Exception { 20. //return new FileInputStream("somefile.rar"); 直接下載 somefile.rar 21. 22. //和 Servlet 中不一樣,這裏我們不需對輸出的中文轉碼爲 ISO8859-1 23. return new ByteArrayInputStream("Struts2 文件下載測試".getBytes()); 24. } 25. 26. //對於配置中的 ${fileName}, 獲得下載保存時的文件名 27. public String getFileName() { 28. DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 29. String fileName = "序列號(" + df.format(new Date()) + ").txt"; 30. try { 31. //中文文件名也是需要轉碼爲 ISO8859-1,否則亂碼 32. return new String(fileName.getBytes(), "ISO8859-1"); 33. } catch (UnsupportedEncodingException e) { 34. return "impossible.txt"; 35. } 36. } 37.} 謹記一個就是,要想下載的文件名不亂碼就要以 ISO8859-1 字符集進行轉碼,內容會否亂碼可在調試中解決。 好啦,啓動服務,訪問 http://localhost:8080/teststruts2/download.action,瀏覽器便會提示下載 序列號(2009-06-17).txt,內容爲:“Struts2 文件下載測試”。 參考:1. 淺談Struts2下載文件的方法實現 2. struts2多文件動態下載及中文解決方案
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章