13.2 文件下载
13.2.1概述
前面学习了文件上传的实现,接下来看看如何实现文件下载的功能。实现文件下载功能的方式也很多,这里只具体看看如何使用Struts2来实现文件下载。
使用Struts2来实现文件下载,会用到它的stream类型的Result,这种Result最终会返回一个InputStream,只需要让这个InputStream能读到用户想要下载的文件即可。
13.2.2 stream结果类型
先来回忆一下stream的结果类型出现在struts-default.xml中的配置,示例如下:
- <package name="struts-default" abstract="true">
- <result-types>
- ...
- <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
- ...
- </result-types>
- ...
- </package>
既然stream是struts-default包中声明的一种内置结果类型,因而只要我们的包继承自struts-default包就可以使用这种结果类型了。
13.2.3实现文件下载的Action
使用stream类型作为Result的Action和普通的Action有很大的不同,它不需要execute方法;而是需要一个公有的,返回InputStream的getInputStream方法,这个方法用来返回文件的内容。示例代码如下:
- public class DownloadAction extends ActionSupport{
- public InputStream getInputStream() throws Exception{
- File file = new File("e:/temp/测试.doc");
- return new FileInputStream(file);
- }
- }
在上面示例中,仅是简单的返回一个读取绝对路径下的文件的输入流。
13.2.4在struts.xml中配置Action
在struts.xml中,需要配置这个Action的后继页面为一个stream类型的Result。
- <package name="helloworld" extends="struts-default">
- <action name="downloadAction" class="cn.javass.fileupload.DownloadAction">
- <result type="stream">
- <param name="contentDisposition">attachment;filename="test.doc"</param>
- </result>
- </action>
- </package>
上面配置中,<action>元素只有一个<result>子元素,其类型为stream;但是<result>元素有一个<param>子元素指定了contentDisposition的值为attachment;filename="test.doc",这指明了在访问这个Result的时候,会弹出一个下载框,其中的默认文件名为test.doc。
stream类型的结果共可以指定7个参数:
- contentType:下载文件的类型。
- contentLength:下载文件的长度,用于浏览器的进度条显示。
- contentDisposition:指定文件下载的默认名字,如果不指定则使用Action名.action。
- inputName:Action中用于返回InputStream的get方法的名字,默认为inputStream,因此,我们的Action中定义了getInputStream的方法。
- bufferSize:缓冲区大小,默认为1k。
- allowCaching:是否允许浏览器进行缓存。
- contentCharSet:HTTP响应头信息中的编码方式。
在以上7个参数中,最常用的是使用contentDisposition来指定默认的文件下载名,其他的使用默认即可。
13.2.5制作下载页面
现在还需要制作一个页面,在这个页面设置一个超链接,链接到下载的Action,示例代码如下:
- <%@ page language="java" contentType="text/html; charset=gb2312"
- pageEncoding="gb2312"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- <title>Insert title here</title>
- </head>
- <body>
- <a href="/helloworld/downloadAction.action">下载文件</a>
- </body>
- </html>
测试运行一下,访问这个页面,点击上面的“下载文件”链接,就会弹出如下保存对话框,其默认文件名就是在struts.xml中配置的test.doc。
图13.4 跳转到downloadAction后弹出的文件下载对话框
13.2.6难道只能在配置文件中写死文件名吗?
看到这里,可能有朋友会想:难道下载的文件名只能在配置文件struts.xml中写死吗?肯定不是的,首先把对应的配置信息去掉,看看Struts2是否能自适应文件名
- <package name="helloworld" extends="struts-default">
- <action name="downloadAction" class="cn.javass.fileupload.DownloadAction">
- <result type="stream">
- </result>
- </action>
- </package>
再次运行,弹出的文件对话框的下载文件名居然直接是“downloadAction.action”,就是action的名称,如下图所示:
图13.5 跳转到downloadAction后弹出的文件下载对话框
看起来不设置contentDisposition属性这条路走不通。那么该怎么做才能让下载显示的文件名称不是写死的呢?
有两种解决的方式。一种就是在Action中提供一个返回文件名称的方法,然后在配置文件中引用这个变量;另外一种方法干脆就去掉配置文件中关于contentDisposition的配置,而直接在Action中提供一个getContentDisposition的方法。
接下来分别看看示例。
1:第一种实现方式
也就是在Action中提供一个返回文件名称的方法,然后在配置文件中引用这个变量,这一个实现方式。此时Action的实现,示例代码如下:
- public class DownloadAction extends ActionSupport{
- public String getDownLoadFileName(){
- return "test.doc";
- }
- public InputStream getInputStream() throws Exception{
- File file = new File("e:/temp/测试.doc");
- return new FileInputStream(file);
- }
- }
在这个Action的实现里面,并没有属性,而直接提供的getDownLoadFileName方法,这是因为OGNL对应访问的就是getter方法。
相应在struts.xml中的配置,示例如下:
- <package name="helloworld" extends="struts-default">
- <action name="downloadAction" class="cn.javass.fileupload.DownloadAction">
- <result type="stream">
- <param name="contentDisposition">attachment;filename=${downLoadFileName}</param>
- </result>
- </action>
- </package>
去运行测试看看,这是否能正确设置下载显示的文件名。
2:第二种实现方式
就是干脆就去掉配置文件中关于contentDisposition的配置,而直接在Action中提供一个getContentDisposition的方法,这样的一种方法。
此时Action的实现,示例代码如下:
- public class DownloadAction extends ActionSupport{
- public String getContentDisposition(){
- return "attachment;filename=\"test3.doc\"";
- }
- public InputStream getInputStream() throws Exception{
- File file = new File("e:/temp/测试.doc");
- return new FileInputStream(file);
- }
- }
相应在struts.xml中的配置,示例如下:
- <package name="helloworld" extends="struts-default">
- <action name="downloadAction" class="cn.javass.fileupload.DownloadAction">
- <result type="stream">
- </result>
- </action>
- </package>
去运行测试看看,这种方式能不能正确设置下载显示的文件名。
13.2.7处理中文文件名
前面的示例,下载显示的都是英文文件名,那么如何让下载显示的是中文的文件名呢?
方法也很简单,就是在Action里面动态设置文件名称的时候,对其按照“ISO8859-1”进行编码,就可以了。
此时的Action,示例代码如下:
- public class DownloadAction extends ActionSupport{
- public String getContentDisposition() throws UnsupportedEncodingException{
- String s = new String("测试".getBytes(),"ISO8859-1");
- return "attachment;filename=\""+s+".doc\"";
- }
- public InputStream getInputStream() throws Exception{
- File file = new File("e:/temp/测试.doc");
- return new FileInputStream(file);
- }
- }
去运行测试看看,应该能正确显示中文的名称了,运行如下图所示:
图13.6 下载提示页面显示中文文件名
私塾在线网站原创《研磨struts2》系列
转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4122.html】
欢迎访问http://sishuok.com获取更多内容