一般來說,文件下載只需要直接在頁面給出一個超級鏈接,該鏈接的href屬性值等於要下載文件的文件名,就可以實現文件下載,如:<a href=”checkbox.rar”>checkbox.rar</a>。但是這樣下載存在着一些缺陷:如果該文件的文件名是中文文件名時,下載則會導致下載失敗;如果在下載時需要對用戶的身份進行判斷,來驗證用戶是否有權限來下載該文件時,那麼單獨的超級鏈接是不可能實現的。這個時候,我們需要用Struts 2來控制文件下載。
Struts 2提供了stream結果類型,該結果類型就是專門用於支持文件下載功能的。通過Struts 2的文件下載支持,允許系統控制瀏覽者下載文件的權限,實現文件名是非西歐字符的文件下載。
首先介紹利用Struts 2實現簡單的文件下載:
public class FileDownloadAction implements Action { public InputStream getInputStream() throws Exception { return new ByteArrayInputStream("Struts 2 下載示例".getBytes()); } public String execute() throws Exception { return SUCCESS; } }
該類只是一個簡單的Action處理類。它提供了一個返回inputStream輸入流的方法。該輸入流代表了下載文件的入口。這個方法用來給被下載的數據提供輸入流。
一、利用Struts 2實現文件名非西歐字符文件下載
有如下一個下載頁面代碼:
<a href="download1.action?p_w_picpath/美女_01.jpg" >下載圖片</a> <a href="download2.action?p_w_picpath/meinv_01.rar">下載壓縮文件</a>
上面頁面中包含了兩個下載的鏈接。但是第一個鏈接資源的文件名爲中文,這時如果我們單擊第一個超級練級,將會出現如下頁面:
從上面的頁面中我們可以看到大量的%字符,很明顯,這種文件名師不能夠實現下載的。這時我們可以使用Struts 2的文件下載支持來下載該文件。
1、實現文件下載的Action
Struts 2的文件下載Action需要提供一個返回InputStream流的方法。
代碼如下:
public class FileDownloadAction extends ActionSupport{ //該屬性可以在配置文件中動態指定該屬性值 private String inputPath; public void setInputPath(String inputPath) { this.inputPath = inputPath; } /*定義一個返回inputStream的方法 * 該方法將作爲下載文件的入口,且需要配置stream類型結果是指定inputName參數 * inputName參數的值就是方法去掉get前綴、首字母小寫的字符串 */ public InputStream getTargetFile() throws Exception{ //servletContext提供getResourceAsStream()方法 //返回指定文件對應的輸入流 return ServletActionContext.getServletContext().getResourceAsStream(inputPath); } @Override public String execute() throws Exception { return SUCCESS; } }
上面的Action中包含了一個getTargetFile()方法,該方法返回一個InputStream輸入流。這個輸入流返回的是下載目標文件的入口。該方法的方法名爲getTargetFile,則stream類型的結果映射中inputName參數值是targetFile.
注:返回InputStream的方法需要配置Stream類型結果時指定inputName參數;該參數值就是方法嗎去掉get前綴,首字母小寫的字符串。
2、配置Action
配置文件下載的Action關鍵是需要配置一個類型爲stream的結果,該stream類型的結果將使用文件下載作爲響應。配置時需要指定以下四個屬性
由於Stream結果類型的邏輯試圖是返回給客服端一個輸入流,因此不需要指定location屬性。
配置如下:
<action name="download1" class="com.app.action.FileDownloadAction"> <!-- 指定被下載資源的位置 --> <param name="inputPath">\p_w_picpath\美女_01.jpg</param> <!-- 配置結果類型爲stream的結果 --> <result name="success" type="stream"> <!-- 指定下載文件的文件類型 --> <param name="contentType">p_w_picpath/jpg</param> <!-- 指定由getTargetFile()方法返回被下載文件的inputStream --> <param name="inputName">targetFile</param> <param name="contentDisposition">p_w_upload;filename="meinv1_01.jpg"</param> <!-- 指定下載文件的緩衝大小 --> <param name="bufferSize">4096</param> </result> </action>
通過上面的配置後,就可以實現包含中文文件名的文件下載了。如果在點擊就可以實現下載了。如下:
二、下載前的授權控制
有時用戶下載文件之前,我們需要對用戶的身份進行驗證,判斷用戶是否具有權限來下載該文件。這時我們通過Struts 2 的文件下載支持,就可以實現下載前的授權控制。
下面的Action,首先通過判斷session裏面的user屬性是否爲chenssy,如果用戶通過了驗證就允許下載,否則直接返回登錄界面。
代碼如下:
public class AuthorityDownAction implements Action { private String inputPath; public void setInputPath(String inputPath) { this.inputPath = inputPath; } public InputStream getTargetFile() throws Exception{ //ServletContext提供了getResourceAsStream()方法 return ServletActionContext.getServletContext().getResourceAsStream(inputPath); } public String execute() throws Exception { //取得ActionContext實例 ActionContext ctx = ActionContext.getContext(); //通過ActionContext訪問用戶的HttpSession Map session = ctx.getSession(); String user = (String) session.get("user"); //判斷session裏的user是否通過檢查 if(user!=null&&user.equals("chenssy")){ return SUCCESS; } ctx.put("tip", "您還沒有登錄,或者登錄的用戶名不正確,請重新登錄!!!"); return LOGIN; } }
上面的Action在校驗失敗後,會返回一個login邏輯視圖名,所以在配置該Action時,還需要配置一個名爲login的結果。
<action name="download2" class="com.app.action.AuthorityDownAction"> <!-- 定義被下載文件的物理資源 --> <param name="inputPath">\p_w_picpath\meinv_01.rar</param> <result name="success" type="stream"> <!-- 指定下載文件的文件類型 --> <param name="contentType">application/rar</param> <!-- 指定由getTargetFile()方法返回被下載文件的InputStream --> <param name="inputName">targetFile</param> <param name="contentDisposition">filename="meinv_01.rar"</param> <!-- 指定下載文件的緩衝大小 --> <param name="bufferSize">4096</param> </result> <result name="login">/login.jsp</result> </action>
通過上面的配置後,就可以實現用戶的授權控制。如果用戶不登錄、或者用戶名不正確,在下載該資源時,就會返回到登錄界面。
如下:
對於處理登錄請求的Action如下:
public class LoginAction extends ActionSupport { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String execute() throws Exception { return SUCCESS; } }
對於該Action,它只是一個簡單的處理類。它的execute方法沒有進行任何處理,直接返回success,表示任何用戶名都可以登錄成功,進入到下載界面,但是從AuthorityDownAction 處理類中可以看到只有用戶名爲chengssy的用戶可以下載成功。其他任何用戶下載該資源都不會成功。
如果登錄成功了,需要返回到下載頁面,所以該Action的配置如下:
<action name="login" class="com.app.action.LoginAction"> <result name="success">/download.jsp</result> </action>
通過上面的一些配置後,用戶再輸入"chengssy",一旦完成了登錄,用戶的session裏username的值就會是:chenssy,這時就可以完成文件的下載了。
PS:如果你覺得文章對你有所幫助,別忘了推薦或者分享,因爲有你的支持,纔是我續寫下篇的動力和源泉!