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"> <! -- 定义downloadFile的Action,其实现类为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元素来设置下载文件路径,代码如下所示。
<! -- 定义downloadFile的Action,其实现类为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> <! -- 指定资源文件baseName为messageResource --> <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> <! -- 定义downloadFile的Action,其实现类为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 用户登录页面