原创作者: 黑暗浪子   阅读:25241次   评论:10条   更新时间:2011-06-01    

技术要点
本节代码详细说明文件下载功能的开发流程,介绍知识点如下:

  上传成功页面重修改后支持文件下载代码内容。
  DownloadAction文件下载功能开发。
  struts.xml中DownloadAction配置,以及支持文件名为中文字符的文件下载。
  下载文件流程展示。


演示代码
上传成功页面,这里笔者让其在每个上传文件后提供“下载”链接。

<!------------------------文件名:result.jsp------------------->
<%@taglib prefix="s" uri="/struts-tags"%>
	<body>
		上传文件:
		<table>
		<!-- 循环显示上传成功文件名 -->
		<s:iterator value="fileFileName" status="fn">
		<tr>
		<td>
		<!-- 上传成功文件名 -->
		<s:property />		
		</td>
		<td>
		<!-- 下载文件链接内容为定义的下载Action -->
		<!-- 下载文件名作为链接参数fileName值,用OGNL表达式表达 -->	
		<a href="<s:url value='download.action'>  				
                 	<s:param name='fileName'
 value='fileFileName[#fn.getIndex()]'/>  
                 </s:url>">下载</a>
		</td>
		</tr>
		</s:iterator>		
		</table>		
	</body>


DownLoadAction类代码

<!------------文件名:DownLoadAction.java ------------------>
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class DownLoadAction extends ActionSupport {
	//下载文件原始存放路径
	private final static String DOWNLOADFILEPATH="/upload/";
	//文件名参数变量
	private String fileName;

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	//从下载文件原始存放路径读取得到文件输出流
	public InputStream getDownloadFile() {
		return 
ServletActionContext.getServletContext().getResourceAsStream(DOWNLOADFILEPATH+fileName);
	}
	//如果下载文件名为中文,进行字符编码转换
	public String getDownloadChineseFileName() {
		String downloadChineseFileName = fileName;

		try {
			downloadChineseFileName = new String(downloadChineseFileName.getBytes(), "ISO8859-1");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return downloadChineseFileName;
	}

	public String execute() {
		return SUCCESS;
	}
}


struts.xml配置文件中有关文件下载的配置:

<!------------------文件名:struts.xml----------------->
<struts>
	<!-- 下载文件的Action定义 -->
		<action name="download" class="action.DownLoadAction">
			<!-- 设置文件名参数,由页面上传入 -->
			<param name="fileName"></param>
			<result name="success" type="stream">
				<!-- 下载文件类型定义 -->
				<param name="contentType">text/plain</param>
				<!-- 下载文件处理方法 -->
				<param name="contentDisposition">
					attachment;filename="${downloadChineseFileName}"
				</param>
				<!-- 下载文件输出流定义 -->
				<param name="inputName">downloadFile</param>
			</result>
		</action>
</struts> 


(1):文件开始下载页面如图4.12所示。

图4.12  文件下载
(2):单击“下载”链接,比如点“下载文件1.txt”文件右边“下载”链接,出现对话框如图4.13所示。

图4.13  下载文件处理方式
(3):单击“保存”按钮后选择下载文件存放路径,如图4.14所示。

图4.14  下载文件选择存放路径


代码解释
(1)在result.jsp中通过iterator标签和url标签定义了“fileFileName”的循环显示以及链接。其中有关“status”和OGNL表达式笔者会在之后章节里具体介绍,这里只是让读者知道是如何使用标签显示图4.12显示的内容。特别指出<param>标签为downloadAction定义了一个参数,该参数名为“fileName”,因为在4.4.1小节中笔者定义的“fileFileName”是个List类型的数据集合,因此利用OGNL表达式将文件名作为“fileName”参数值传入downloadAction中。
(2)DownLoadAction文件中先定义了常量DOWNLOADFILEPATH,它是下载文件在服务器存放的路径名,也就是4.4.1小节中上传文件在服务器存放的路径名。
定义好DOWNLOADFILEPATH后,在定义DownLoadAction的属性变量。因为在result.jsp中定义了参数“fileName”,则它作为DownLoadAction的属性变量,需要定义相应的getter、setter方法。
然后定义了getDownloadFile方法,它返回的是一个文件流,表明将被下载文件转换为输出流,方便下载。利用Struts2自带的“ServletActionContext”类的API把下载文件存放路径作为方法参数,读取下载文件,将其转换为文件流。
还有一个getDownloadChineseFileName方法,该方法主要作用是将文件名为中文字符的文件进行文件名的字符编码集合转换。因为在Web系统中由JSP等视图页面传入的变量值,特别是中文字符的变量。缺省的字符编码集合都是“ISO8859-1”,因此利用Java的字符串类的API,将字符编码转成开发需要的字符编码集。防止中文字符乱码问题发生。
(3)struts.xml中定义了名为“download”的Action。其中它自己的参数“fileName”因为在这里它的值会从JSP页面上传入,所以这里只是定义,没有具体给它赋任何值
在<result>标签中定义了type属性,值为“stream”。如果是下载文件功能开发,DownLoadAction一定要设置type属性,而且值为“stream”。这是因为在Struts2自带的xml配置文件为struts-default.xml中有关于“stream”的result返回类型的定义,代码如下:

<!-------------------文件名:struts-default.xml-------------->
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>


这里Struts2定义了result返回类型为“stream”,这个result类型主要是处理文件的输入和输出流时候需要使用的。因为下载文件就是把文件转换成输入输出流,将其从一个文件路径放到另外一个文件路径中去。所以肯定要设置这个result类型的。
“contentType”、“contentDisposition”、“inputName”都是这个result的属性。“contentType”就是文件类型。这里因为下载的文件是文本文件,因此设定的值为文本文件类型,具体各个文件类型如何定义,4.4.1小节已经介绍过,这里不再做说明。“contentDisposition”是指定下载文件处理方式,如图4.13就是处理方式的效果。特别指出如果“contentDisposition”定义的值把前面的“attachment”去掉,则下载方式不是以附件方式下载,如果单击“下载”链接,则会把下载文件的内容显示在浏览器中。读者可以去试验一下。这里有个“${downloadChineseFileName}”,这就是在DownLoadAction中定义getDownloadChineseFileName方法的目的,${downloadChineseFileName}是OGNL的表达式,它显示了“downloadChineseFileName”变量的具体值,因为在DownLoadAction中定义getDownloadChineseFileName方法,则把已经转换成符合需要字符编码集的下载文件名作为下载文件方式对话框中显示的名称,不会造成任何乱码问题。“inputName”是最关键的一个属性,也是一定要定义的属性,“inputName”参数中定义的值“downloadFile”就是DownLoadAction中getDownloadFile方法返回的文件流名字。在Struts2中Acion用前缀名为get的方法得到各种属性的值,这些属性有些是在Action中定义,有些就像本示例在配置文件中利用OGNL表达式或直接定义。
(4)开始进行文件下载功能展示,按照如上记述的步骤执行即可。笔者将两个文本文件上传上去,然后在上传成功页面对具体的文件进行下载。在图4.13中单击“保存”按钮就显示图4.14,选择在本机上存放下载文件的路径即可完成下载文件功能。

评论 共 10 条 请登录后发表评论
10 楼 ccttvvbb 2011-11-10 11:19
楼主,中文还是乱码, 解决不了!
9 楼 fxn19870827 2011-09-21 13:30
8 楼 浪子柔情 2011-08-14 23:29
楼主:

    我最近也做了一个接口,也要用到这些,现在比方说,你访问我的页面,在页面上会有个按钮,点击按钮之后,程序会自动去数据库取数据打包成zip架包,我现在要做的就是,在你点击那个按钮的时候,要有个提示框,可以让访问者自己选择下载的路径,然后存放在选择的那个地方,其他的我都做好了,就剩下这里了,能不能不能action在javaBean里面写,或者在jsp里面实现这点?LZ能不能给个建议,我等你回信!

    方便的话  我QQ1462552695  可以给指点一下  谢了 很急
7 楼 gq2010 2011-06-21 17:06
如果文件不服务内部怎么办啊?
6 楼 jax8259834 2011-05-10 19:49
还是没有实现解决中文乱码的问题,不过还是感谢楼主的讲义~讲得很不错
5 楼 hengly 2011-03-27 16:33
当文件名是中文的时候,url的参数传递过去是乱码。
4 楼 daoba13 2011-03-03 20:09
非常感谢,我都要感动的哭了!
3 楼 release 2009-10-28 15:01
上个项目遇到过CentOS下的乱码问题,需要在下载方法中显示定义
ServletActionContext.getResponse().setHeader("Content-Disposition", "attachment; filename="+new String(file_name.getBytes("gb2312"),"iso-8859-1);
楼主归纳的很详尽了
2 楼 黑暗浪子 2009-10-19 09:10
release 写道
楼主你确定用LINUX做服务器你的下载不会产生中文乱码?

不好意思,我没有用linux试过。如果有缺陷,你可以帮我补充,谢谢~
1 楼 release 2009-10-17 16:49
楼主你确定用LINUX做服务器你的下载不会产生中文乱码?

发表评论

您还没有登录,请您登录后再发表评论

文章信息

Global site tag (gtag.js) - Google Analytics