其实有很多人都写过关于struts2下载问题的帖子或博文,但感觉说的不是很系统和清楚,所以笔者就自己的理解来总结一下自己对这个下载方法的理解和应用。
首先,struts2上传和下载比用原始的方法简便很多,所以它比较受亲睐,但要理解好了才能应用;
其次,它表面上看起来很简单但实际上里面的逻辑关系和参数关系比较复杂;
第三,很多人都写过这个代码但是很多时候会报错,如下图:
报着个错就是没有真正理解配置文件中路径问题,这个错误本身不是找不到输入流"targetFile"而是输入流没有找到你规定的要下载的文件,输入流就空(我在下面的Action代码中有判断输入流是否为空的if...else...语句)。
先来看看代码,边看边解释吧。
1.JSP代码:
<a href="DownLoadAction.action">Excel下载</a>
JSP显示效果如下图:
2.DownLoadAction代码:
先把几个参数或方法的作用介绍一下吧:
Sting inputPath(参数):这个是下载文件的全路径(包含名称),即从什么地方下载什么文件和下载的是那个文件;
InputStream getTarGetFile()(方法):这个方法是为下载文件提供输入流,看其返回值就知道了,就是以流的形式读取文件,也可以说是下载文件的源;
注:要想真正体会这个参数和这个方法的作用和意义,还是看看配置文件后理解的更透彻。
package action;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownLoadAction extends ActionSupport {
private String inputPath;
// 依赖注入该属性值的setter方法
public void setInputPath(String value) {
inputPath = value;
}
//让Action获得targetFile属性,即输入流
public InputStream getTargetFile() throws Exception {
System.out.println("执行到这儿了吗?");
if (ServletActionContext.getServletContext().getResourceAsStream(
inputPath) == null) {
System.out.println("路径:"+inputPath);
System.out.println("输入流为空");
} else {
System.out.println("输入流不为空");
}
return ServletActionContext.getServletContext().getResourceAsStream(
inputPath);
}
//让execute()方法来执行Action
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("这个方法应该执行了!");
return "success";
}
}
3.*struts.xml配置文件代码(重要)
<action name="DownLoadAction" class="action.DownLoadAction">
<param name="inputPath">\test.xls</param>
<result name="success" type="stream">
<param name="contentType">application/vnd.ms-excel</param>
<param name="inputName">targetFile</param>
<param name="contentDisposition">filename="linux.xls"</param>
<param name="bufferSize">1024</param>
</result>
</action>
看这代码来逐行解释其含义:
<param name="inputPath">\test.xls</param>:这一行是告诉Action下载文件的路径,这个"\test.xls",不是随便的路径,是有要求的;
这个路径的真实含义:H:\MyEclipse 9\.metadata\.me_tcat\webapps\excel\test.xls,
解释下:MyEclipse 9是我的myeclipse的工作空间名称;
在其下有个.metadata文件夹;
再下一层有个.me_tcat\webapps;
而excel是我的项目的名称;
test.xls就是要下载的文件。
其实,这个路径就是javaweb项目在Tomcat下加载后"webapps\项目名称\要下载的文件名称"(我用的是myeclipse自带的Tomcat)。
<result name="success" type="stream">:这一行,name属性没什么好说的,至于type属性如果不懂得可以上百度上看看,struts2 Action配置相关文章,这里也不多说了。
<param name="contentType">application/vnd.ms-excel</param>:这一行也很重要,contentType属性标识要下载的文件的类型,下载的时候是以流的形式下载的,这个属性可以让Action知道下载后把这个文件写成什么类型的文件。
这个要是不了解不多的,可以参照http://baike.baidu.com/view/1547292.htm看看下面的常用类型。
<param name="inputName">targetFile</param>:这一行是和Action中的那个getTargetFile()方法相对应,就是告诉Action一个输入流,让Action知道从哪儿读取文件流。
<param name="contentDisposition">filename="linux.xls"</param>:这一行中contentDisposition属性有一下作用:
Content-disposition头提供给浏览器确定HTTP响应内容的信息。当浏览器读到这些头信息后,它能确定:
A. HTTP响应包含一个文件;
B. 包含在响应中的文件名;
C. 该文件是显示在浏览器主窗口中还是要用外部的应用查看;
这个属性可以不配置,也可以配置成"attachment"和"inline",配置成前者后servlet就指示浏览器把文件当成附件处理,而配置成后者servlet就指示浏览器把文件"内嵌"显示文件。
这个要是不了解不多的,可以参照http://wfwkiss.iteye.com/blog/528410看看详细的说明和解释。
<param name="bufferSize">1024</param>:这一行就很简单了,就是以字节为单位规定缓冲区的大小。
好了,用了一个小时来总结这些,一方面是把自己学习过的知识有个总结,另一方面是可以帮助到那些对这些问题还不是很懂的朋友们,都1:30了,在不睡明天又起不了了。
大家晚安!