使用Struts 2控制文件下載

    一般來說,文件下載只需要直接在頁面給出一個超級鏈接,該鏈接的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",一旦完成了登錄,用戶的sessionusername的值就會是:chenssy,這時就可以完成文件的下載了。


 

PS:如果你覺得文章對你有所幫助,別忘了推薦或者分享,因爲有你的支持,纔是我續寫下篇的動力和源泉!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章