零基础学Struts
上QQ阅读APP看书,第一时间看更新

7.5 文件下载

通过Struts 2的文件下载支持可以轻松地完成文件下载,而且还可以实现中文文件名下载。通过Struts 2文件下载支持与拦截器相结合可以实现文件的下载权限控制。

7.5.1 使用Struts 2配置文件下载

前面介绍的都是文件上传的知识,下面来看如何实现文件下载。有朋友肯定会问提出,实现文件下载很简单啊!只要给出该文件的超链接不就行了吗?

那下面就按照这样的方法,使用超链接来实现文件下载。首先在Web项目根目录下添加一个文件夹dowload,在该文件夹下放置一个压缩文件1.zip。编写下载页面“dowload.jsp”,添加该文件的下载链接,代码如下所示。

    <%@ page language="java" pageEncoding="gb2312"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>
    <html>
      <head>
        <title>文件下载</title>
      </head>
        <center>
        <h1>文件下载</h1>
        <a href="download/1.zip">链接方式下载</a>
      </center>
      <body>
      </body>
    </html>

接下来打开文件下载页面“dowload.jsp”,如图7.31所示。单击“链接方式下载”链接进行下载。

这是出现了“文件下载”对话框,发现确实可以通过超链接来实现下载,如图7.32所示。

图7.31 使用超链接方式实现下载

图7.32 “文件下载”对话框

下面将该文件名替换成中文,如“复件1.zip”,并修改下载链接,代码如下所示。

    <a href="download/复件1.zip">链接方式下载</a>

再次单击该下载链接进行下载,文件下载出错,如图7.33所示。

图7.33 找不到文件路径

文件名称变成了包含大量%的字符串,为什么会这样呢?因为URL将文件名给解析了,如果文件名为英文,那么解析后仍然是原来的文件名,所以就能成功实现下载;如果文件名包含中文,那么链接就成了解析后的字符串了,当然就无法找到并下载该文件了。

那么如何才能下载这种中文文件名的文件呢?其实可以使用Struts 2的文件下载支持来实现文件下载。首先在下载页面中添加一个下载链接,链接到一个Action,代码如下所示。

        <%@ page language="java" pageEncoding="gb2312"%>
        <%@ taglib prefix="s" uri="/struts-tags"%>
        <html>
          <head>
            <title>文件上传</title>
          </head>
              <center>
              <h1>文件下载</h1>
              <a href="download/复件1.zip">链接方式下载</a>
              <a href="downloadFile.action" >通过Action完成下载</a>
          </center>
          <body>
          </body>
        </html>

7.5.2 实现文件下载Action

新建文件下载Action,该Action与以前创建的Action没有太大的不同。不过如果要实现文件下载,必须为该Action提供一个返回InputStream流的方法,代码如下所示。

        package net.hncu.struts2.action;
        import java.io.InputStream;
        import org.apache.struts2.ServletActionContext;
        import com.opensymphony.xwork2.ActionSupport;
        public class DownloadAction extends ActionSupport {
              //该方法返回需要被下载文件的输入流
              public InputStream getDownload(){
                    return ServletActionContext.getServletContext().getResourceAsStream("/download/复件1.zip");
              }
              public String execute() throws Exception {
                    return SUCCESS;
              }
        }

这里使用ServletContext的getResourceAsStream()返回被下载文件的输入流。

7.5.3 配置该文件下载Action

下面需要对文件下载Action进行配置,这里与前面不同的是需要配置该Action的一个类型为stream的结果。可以通过“struts-default.xml”文件查看stream结果的配置,代码如下所示。

        <result-types>
        ...
        <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
    ...
    </result-types>

从stream结果的配置可以看出,其对应的实现类为StreamResult,代码如下所示。

    public class StreamResult extends StrutsResultSupport {
    ...
        protected String contentType = "text/plain";
        protected String contentLength;
        protected String contentDisposition = "inline";
        protected String inputName = "inputStream";
        protected InputStream inputStream;
        protected int bufferSize = 1024;
    ...
    }

❑ contentType:用来指定下载文件的文件类型。

❑ contentLength:文件大小,无需指定,也不能指定。

❑ contentDisposition:指定下载的文件名。

❑ inputName:指定被下载文件的输入流入口,与下载Action中获得输入流的方法相对应。如Action中获得输入流的方法名为getDownload,那么inputName就应配置成dowload。

❑ inputStream:输入流,无需指定,也不能指定。

❑ bufferSize:指定下载文件时的缓冲大小。

下面根据下载Action配置该Action类,代码如下所示。

    <? xml version="1.0" encoding="UTF-8" ? >
    <! DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    <! -- struts为配置文件根元素-->
    <struts>
          <! -- 设置参数编码格式 -->
          <constant name="struts.i18n.encoding" value="gb2312"></constant>
          <! -- Action必须放在指定的包名空间中-->
          <package name="struts2" extends="struts-default">
              <! -- 定义downloadFileAction,其实现类为net.hncu.struts2.action.DownloadAction2-->
              <action name="downloadFile"
                    class="net.hncu.struts2.action.DownloadAction">
                    <! -- 定义处理结果与视图资源之间的关系-->
                    <result name="success" type="stream">
                        <param name="inputName">download</param>
                        <param name="contentType">application/zip</param>
                        <param name="contentDisposition">filename="my.zip"</param>
                    </result>
                </action>
          </package>
    </struts>

再次单击包含中文文件名的文件的下载链接,这时发现可以下载该文件了,如图7.34所示。

图7.34 “文件下载”对话框

7.5.4 动态设置下载文件路径

前面通过Struts 2的文件下载支持实现了文件下载,但是这里有一个问题。如果想要修改文件的下载地址,就必须修改文件下载Action,这样比较麻烦。

下面就来看如何动态地设置下载文件路径。首先在文件下载Action中添加一个属性filePath表示下载文件路径,并添加其setter和getter方法,代码如下所示。

        package net.hncu.struts2.action;
        import java.io.InputStream;
        import org.apache.struts2.ServletActionContext;
        import com.opensymphony.xwork2.ActionSupport;
        public class DownloadAction2 extends ActionSupport {
              //下载文件地址
              private String filePath;
              //获得下载文件地址
              public String getFilePath() {
                    return filePath;
              }
              //设置下载文件地址
              public void setFilePath(String filePath) {
                    this.filePath = filePath;
              }
              //该方法返回需要被下载文件的输入流
              public InputStream getDownload(){
                    return ServletActionContext.getServletContext().getResourceAsStream("getFilePath()");
              }
              public String execute() throws Exception {
                    return SUCCESS;
              }
        }

在配置Action中通过添加param元素来设置下载文件路径,代码如下所示。

        <! -- 定义downloadFileAction,其实现类为net.hncu.struts2.action.DownloadAction2-->
        <action name="downloadFile"
              class="net.hncu.struts2.action.DownloadAction2">
              <! -- 指定下载文件地址 -->
              <param name="filePath">/download/复件1.zip</param>
              <! -- 定义处理结果与视图资源之间的关系-->
              <result name="success" type="stream">
                    <param name="inputName">download</param>
                    <param name="contentType">application/zip</param>
                      <param name="contentDisposition">filename="myFile.zip"</param>
                </result>
          </action>

这样就可以动态地设置下载文件的路径了,当要修改下载文件路径时只需修改该配置文件。

7.5.5 使用拦截器增加下载权限控制

通过Struts 2的文件下载支持,还可以为下载文件添加权限控制。下载权限控制也是非常常用的,比如一些下载站点,都要求登录以后才能下载。那如何才能实现文件下载权限控制呢?答案就是使用拦截器。下面来看如何通过使用拦截器增加下载权限控制。

首先将以前的登录案例及权限控制拦截器复制到这个项目中,然后为下载Action配置权限控制拦截器,代码如下所示。

        <! -- struts为配置文件根元素-->
        <struts>
              <! -- 设置参数编码格式 -->
              <constant name="struts.i18n.encoding" value="gb2312"></constant>
              <! -- 指定资源文件baseNamemessageResource -->
              <constant name="struts.custom.i18n.resources"
                    value="messageResource">
              </constant>
              <! -- Action必须放在指定的包名空间中-->
              <package name="struts2" extends="struts-default">
                    <! -- 配置权限控制拦截器 -->
                    <interceptors>
                            <interceptor name="authInter"
                            class="net.hncu.interceptor.AuthInterceptor">
                            </interceptor>
                    </interceptors>
                    <! -- 定义downloadFileAction,其实现类为net.hncu.struts2.action.DownloadAction2-->
                    <action name="downloadFile"
                          class="net.hncu.struts2.action.DownloadAction2">
                          <! -- 指定下载文件地址 -->
                          <param name="filePath">/download/复件1.zip</param>
                          <! -- 定义处理结果与视图资源之间的关系-->
                          <result name="success" type="stream">
                              <param name="inputName">download</param>
                              <param name="contentType">application/zip</param>
                              <param name="contentDisposition">
                                    filename="myFile.zip"
                              </param>
                        </result>
                        <result name="login">/login.jsp</result>
                        <interceptor-ref name="authInter"></interceptor-ref>
                        <interceptor-ref name="defaultStack"></interceptor-ref>
                    </action>
              </package>
        </struts>

注意

如果要实现登录还必须配置登录Action。

这时再单击下载链接,页面跳转到了登录页面如图7.35所示,表示成功地完成了文件下载权限控制。

图7.35 用户登录页面