1 使用Struts2控制文件下载
可能很多人会觉得,文件下载太简单,直接在页面上给出一个超级链接,该链接的href属性等于要下载文件的文件名,不就可以实现文件下载了吗?大部分时候的确可以实现文件下载,但如果该文件的文件名为中文文件名,则会导致下载失败;或者应用程序需要在让用户下载之前进行进一步检查,比如判断用户是否有足够权限来下载该文件等。
看下面的一个原始的下载页面代码片段:
<h1>原始的下载</h1>
<ul><li>
<!-- 包含中文文件名的下载链接 -->
下载Struts2的Logo:<a href="images/中.gif">下载图形文件</a>
</li><li>
下载Struts2的Logo的压缩文件:<a href="images/struts-gif.zip">下载压缩文件</a>
</li></ul>
上面页面的包含两个下载的超级链接,两个链接的资源都是存在的,但因为第一个资源文件的文件名是中文文件名,如果单击第一个超级链接,将出现如下图所示的页面。
从图中页面中椭圆形框包围的地方,我们看到被下载的文件名变成了包含大量%的字符串,很明显,这种文件名显然无法取得需要下载的文件。
为了解决这个问题,我们使用Struts2的文件下载支持来下载该文件。
2 实现文件下载的Action
Struts2的文件下载Action与普通的Action并没有太大的不同,仅仅是该Action需要提供一个返回InputStream流的方法,该输入流代表了被下载文件的入口。该Action类的代码如下:
public class FileDownloadAction implements Action
{
//该属性是依赖注入的属性,该属性可以在配置文件中动态指定该属性值
private String inputPath;
//依赖注入该属性值的setter方法
public void setInputPath(String value)
{
inputPath = value;
}
/*
下载用的Action应该返回一个InputStream实例,
该方法对应在result里的inputName属性值为targetFile
*/
public InputStream getTargetFile() throws Exception
{
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
//处理用户请求的execute方法,该方法返回success字符串
public String execute() throws Exception
{
return SUCCESS;
}
}
从上面的Action中看到,该Action中包含了一个getTargetFile()方法,该方法返回一个InputStream输入流,这个输入流返回的是下载目标文件的入口。该方法的方法名为getTargetFile,表明该Action有一个targetFile属性来返回下载文件。
一旦我们定义了该Action,就可通过该Action来实现文件下载。
3 配置Action
配置该文件下载的Action与配置普通的Action并没有太大的不同,需要在配置普通Action的基础之上,在加上额外的download的拦截器引用。
除此之外,关键是需要配置一个类型为stream的结果,配置stream类型的结果时需要指定如下四个属性:
contentType:指定被下载文件的文件类型。
inputName:指定被下载文件的入口输入流。
contentDisposition:指定下载的文件名。
bufferSize:指定下载文件时的缓冲大小。
因为stream结果类型的逻辑视图是返回给客户端一个输入流,因此无需指定location属性。
提示:配置stream类型的结果时,因为无需指定实际的显示的物理资源,所以无需指定location属性,只需要指定inputName属性,该属性指向被下载文件。
下面是配置该下载所用的Action类的配置文件片段:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Struts2配置文件的DTD信息 -->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- 配置Struts2国际化资源文件的baseName -->
<constant name="struts.custom.i18n.resources" value="globalMessages"/>
<!-- 配置Struts2应用的编码集 -->
<constant name="struts.i18n.encoding" value="GBK"/>
<package name="lee" extends="struts-default">
<!-- 配置下载的拦截器引用 -->
<default-action-ref name="download"/>
<action name="download" class="lee.FileDownloadAction">
<!-- 指定被下载资源的位置 -->
<param name="inputPath">\images\中.gif</param>
<!-- 配置结果类型为stream的结果 -->
<result name="success" type="stream">
<!-- 指定下载文件的文件类型 -->
<param name="contentType">image/gif</param>
<!-- 指定下载文件的文件位置 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">filename="struts.gif"</param>
<!-- 指定下载文件的缓冲大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
</package>
</struts>
可能很多人会觉得,文件下载太简单,直接在页面上给出一个超级链接,该链接的href属性等于要下载文件的文件名,不就可以实现文件下载了吗?大部分时候的确可以实现文件下载,但如果该文件的文件名为中文文件名,则会导致下载失败;或者应用程序需要在让用户下载之前进行进一步检查,比如判断用户是否有足够权限来下载该文件等。
看下面的一个原始的下载页面代码片段:
<h1>原始的下载</h1>
<ul><li>
<!-- 包含中文文件名的下载链接 -->
下载Struts2的Logo:<a href="images/中.gif">下载图形文件</a>
</li><li>
下载Struts2的Logo的压缩文件:<a href="images/struts-gif.zip">下载压缩文件</a>
</li></ul>
上面页面的包含两个下载的超级链接,两个链接的资源都是存在的,但因为第一个资源文件的文件名是中文文件名,如果单击第一个超级链接,将出现如下图所示的页面。
从图中页面中椭圆形框包围的地方,我们看到被下载的文件名变成了包含大量%的字符串,很明显,这种文件名显然无法取得需要下载的文件。
为了解决这个问题,我们使用Struts2的文件下载支持来下载该文件。
2 实现文件下载的Action
Struts2的文件下载Action与普通的Action并没有太大的不同,仅仅是该Action需要提供一个返回InputStream流的方法,该输入流代表了被下载文件的入口。该Action类的代码如下:
public class FileDownloadAction implements Action
{
//该属性是依赖注入的属性,该属性可以在配置文件中动态指定该属性值
private String inputPath;
//依赖注入该属性值的setter方法
public void setInputPath(String value)
{
inputPath = value;
}
/*
下载用的Action应该返回一个InputStream实例,
该方法对应在result里的inputName属性值为targetFile
*/
public InputStream getTargetFile() throws Exception
{
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
//处理用户请求的execute方法,该方法返回success字符串
public String execute() throws Exception
{
return SUCCESS;
}
}
从上面的Action中看到,该Action中包含了一个getTargetFile()方法,该方法返回一个InputStream输入流,这个输入流返回的是下载目标文件的入口。该方法的方法名为getTargetFile,表明该Action有一个targetFile属性来返回下载文件。
一旦我们定义了该Action,就可通过该Action来实现文件下载。
3 配置Action
配置该文件下载的Action与配置普通的Action并没有太大的不同,需要在配置普通Action的基础之上,在加上额外的download的拦截器引用。
除此之外,关键是需要配置一个类型为stream的结果,配置stream类型的结果时需要指定如下四个属性:
contentType:指定被下载文件的文件类型。
inputName:指定被下载文件的入口输入流。
contentDisposition:指定下载的文件名。
bufferSize:指定下载文件时的缓冲大小。
因为stream结果类型的逻辑视图是返回给客户端一个输入流,因此无需指定location属性。
提示:配置stream类型的结果时,因为无需指定实际的显示的物理资源,所以无需指定location属性,只需要指定inputName属性,该属性指向被下载文件。
下面是配置该下载所用的Action类的配置文件片段:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Struts2配置文件的DTD信息 -->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- 配置Struts2国际化资源文件的baseName -->
<constant name="struts.custom.i18n.resources" value="globalMessages"/>
<!-- 配置Struts2应用的编码集 -->
<constant name="struts.i18n.encoding" value="GBK"/>
<package name="lee" extends="struts-default">
<!-- 配置下载的拦截器引用 -->
<default-action-ref name="download"/>
<action name="download" class="lee.FileDownloadAction">
<!-- 指定被下载资源的位置 -->
<param name="inputPath">\images\中.gif</param>
<!-- 配置结果类型为stream的结果 -->
<result name="success" type="stream">
<!-- 指定下载文件的文件类型 -->
<param name="contentType">image/gif</param>
<!-- 指定下载文件的文件位置 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">filename="struts.gif"</param>
<!-- 指定下载文件的缓冲大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
</package>
</struts>