4.1 小节中对所有 Struts2 缺省定义的拦截器作了介绍。其中有个“ fileUpload ”拦截器,本节就针对该拦截器在开发中如何实现文件上传下载功能做一个简单说明。在正式说明之前,还需要在 Web 项目中导入支持文件上传下载和 IO 输入输出的两个 jar 包。它们名字为 commons-fileupload-1.2.1.jar 和 commons-io-1.4.jar ,这两个包都可以在 apache 网站上可以下载到,笔者下载的是它们的最新版本,请读者自行去下载,并参考附录 3 中笔者说明的如何在 MyEclipse 中,导入 Web 项目所支持的程序包的步骤把这两个包导入到 Web 项目中。
4.4.1 Struts2 文件上传功能开发
技术要点
本节代码详细说明文件上传功能的开发流程,介绍知识点如下:
= 文件上传页面和显示上传成功页面代码内容。
= UploadAction 类中实现上传功能方法和上传文件属性介绍。
= struts.xml 中 UploadAction 配置,以及字符编码、文件临时存放路径配置。
= 上传后所处路径和最终上传成功后效果展示。
演示代码
上传文件页面,这里笔者定义的是多个文件上传。
<!------------------------------------------- 文件名: upload.jsp-------------------------------->
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title> 上传文件 </title>
</head>
<body>
<!-- 上传文件表单定义 -->
<s:form action="upload" method="post" enctype="multipart/form-data" >
<tr>
<!-- 上传文件标签定义 -->
<td> 上传文件 :<s:file name="file"></s:file></td>
</tr>
<tr>
<td> 再次上传文件 :<s:file name="file"></s:file></td>
</tr>
<tr>
<td align="left"><s:submit name="submit" value=" 提交 "></s:submit></td>
</tr>
</s:form>
</body>
</html>
上传文件成功后结果页面
<!------------------------------------------- 文件名: result.jsp -------------------------------->
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title> 上传结果 </title>
</head>
<body>
上传文件:
<!-- 显示上传成功文件名 -->
<s:property value="fileFileName" />
</body>
</html>
UploadAction 类代码
<!------------------------------------------- 文件名: UploadAction .java -------------------------------->
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
// 文件上传 Action
public class UploadAction extends ActionSupport {
// 上传文件存放路径
private final static String UPLOADDIR = "/upload";
// 上传文件集合
private List<File> file;
// 上传文件名集合
private List<String> fileFileName;
// 上传文件内容类型集合
private List<String> fileContentType;
public List<File> getFile() {
return file;
}
public void setFile(List<File> file) {
this.file = file;
}
public List<String> getFileFileName() {
return fileFileName;
}
public void setFileFileName(List<String> fileFileName) {
this.fileFileName = fileFileName;
}
public List<String> getFileContentType() {
return fileContentType;
}
public void setFileContentType(List<String> fileContentType) {
this.fileContentType = fileContentType;
}
public String execute() throws Exception {
for (int i = 0; i < file.size(); i++) {
// 循环上传每个文件
uploadFile(i);
}
return "success";
}
// 执行上传功能
private void uploadFile(int i) throws FileNotFoundException, IOException {
try {
InputStream in = new FileInputStream(file.get(i));
String dir = ServletActionContext.getRequest ().getRealPath(UPLOADDIR );
File uploadFile = new File(dir, this.getFileFileName().get(i));
OutputStream out = new FileOutputStream(uploadFile);
byte[] buffer = new byte[1024 * 1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
struts.xml 配置文件中有关文件上传的配置:
<!------------------------------------------- 文件名: struts.xml-------------------------------->
<struts>
<!-- 系统常量定义,定义上传文件字符集编码 -->
<constant name="struts.i18n.encoding" value="gb2312"></constant>
<!-- 系统常量定义,定义上传文件临时存放路径 -->
<constant name="struts.multipart.saveDir" value="c:\"></constant>
<!-- Action 所在包定义 -->
<package name="C04.4" extends="struts-default">
<!-- Action 名字,类以及导航页面定义 -->
<!-- 通过 Action 类处理才导航的的 Action 定义 -->
<action name="upload" class="action.UploadAction">
<result name="input">/jsp/upload.jsp</result>
<result name="success">/jsp/result.jsp</result>
</action>
</package>
</struts>
( 1 ):文件上传页面如图 4.8 所示。
图 4.8 文件上传
( 2 ):选择文件如图 4.9 所示。
图 4.9 选择上传的文件
( 3 ):单击“提交”按钮后文件上传成功页面,并显示上传文件名,如图 4.10 所示。
图 4.10 上传文件成功后效果
( 4 ):两个被上传文件最终在服务器上存放路径效果如图 4.11 所示。
图 4.11 上传文件存放路径图
代码解释
( 1 )在 upload.jsp 中通过 Form 标签和 File 标签定义了两个上传文件。 Struts2 标签笔者会在之后章节里具体介绍,这里只是让读者知道是如何使用标签显示图 4.8 显示的内容。如果上传成功,笔者在 result.jsp 中“ [ ”和“ ] ”之间显示上传文件的文件名,如果是多个文件,以“,”相隔。这些显示格式都是用 Property 标签定义的。
注意:如果上传文件,在 JSP 的 Form 中一定要定义如 upload.jsp 文件中黑体表示的部分。 method 和 enctype 属性都必须要如代码中所示。这样 Form 中上传文件才会起作用。
( 2 ) UploadAction 文件中先定义了常量 UPLOADDIR ,它是上传文件上传后存放的文件夹名字。比如笔者使用的是 JBoss (附录中有安装和在 MyEclipse 中部署的操作说明),则在它的已部署 Web 项目下的 upload 文件夹中,会有所有上传成功的文件。如图 4.11 读者也可以看见它的上传文件最终存放路径。
注意:在 MyEclipse 中开发的“ WebRoot ”目录下也要新建一个 upload 文件夹,否则部署后在 JBoss 的已部署 Web 项目下将没有 upload 文件夹。因为部署的时候会将所有“ WebRoot ”目录下的文件夹和文件都部署到 JBoss 的已部署 Web 项目下。
定义好 UPLOADDIR 后,在定义上传文件的属性变量。也许其中的“ fileFileName ”和“ fileContentType ”读者看了有点别扭,尤其是“ fileFileName ”感觉不符合 Java 命名规范,但是这两个属性变量是 4.1 小节中介绍的“ fileUpload ”拦截器类中的类公有变量名字,只有这样定义, UploadAction 执行时候会把在页面上选择的上传文件的属性值放在这两个变量里面,否则调试 UploadAction 时候会发现这两个变量都会是“ null ”即空值。不相信的读者可以自行改变这两个变量名再执行上传文件功能进行调试看一下这两个变量得到的值。
注意:因为这里笔者是进行多个文件上传功能开发,因此“ file ”、“ fileFileName ”、“ fileFileName ”属性变量都设定为 List 类型,其实还可以设定为数组类型。个人觉得没有啥大区别。完全凭个人喜好而定。还有如果读者自己开发单个文件上传,就没必要把它们设定为 List 类型或数组类型。直接把“ file ”定义为 Java 的 IO 包中的 File 类型,“ fileFileName ”、“ fileFileName ”定义为普通的 String 类型即字符串类型。
之后在 execute 方法中,写一个循环,对所有页面中选择的上传文件一个个进行上传。这里笔者运用了重构中的“抽取方法”的方式,将上传文件的功能封装成一个私有方法,名字为“ uploadFile ”。其中运用了 Java 的 IO 包中很多 API 方法。有对重构和 Java 的 IO 功能不了解的读者可以去查阅相关资料去理解掌握,这里不是本书以及本节重点,因此不再具体记述。
( 3 ) struts.xml 中定义了 <constant> 标签,主要定义了文件名和文件内容显示的字符编码集以及这些被上传文件临时存放路径。
先说明一下 <constant> 标签,顾名思义这是定义整个 Web 项目的一些常量属性值,如果不定义则在 Struts2 自带的 default.properties (读者们可到自己安装 Struts2 的文件路径 src\core\src\main\resources\org\apache\struts2\ 下找到)文件中有这些常量的定义,比如在本节 struts.xml 文件中的“ struts.i18n.encoding ”和“ struts.multipart.saveDir ”在 default.properties 定义代码如下:
<!------------------------------------------- 文件名: default.properties-------------------------------->
### This can be used to set your default locale and encoding scheme
# struts.locale=en_US
struts.i18n.encoding=UTF-8
### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser=jakarta
# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
如果不在 struts.xml 文件中定义,则 Web 项目会缺省使用 default.properties 文件中这两个常量属性的定义。一个将使字符编码集变为“ UTF-8 ”,另一个干脆没有任何文件路径指定。而笔者开发的该 Web 项目缺省支持的字符编码集是“ gb2312 ”,而且需要指定临时上传文件存放路径。(当然如果读者开发的 Web 项目缺省编码集就是“ UTF-8 ”,而且也并不需要指定临时路径时候,就没必要在 struts.xml 中定义这两个 <constant> ),因此有必要定义这两个属性符合项目开发要求。
注意:也可以如第 3 章那样,把这两个属性定义在自定义的 struts.properties 文件中,具体代码可以如下:
<!------------------------------------------- 文件名:struts.properties-------------------------------->
struts.i18n.encoding =gb2312
struts.multipart.saveDir= c:\
笔者个人认为比在 struts.xml 中定义更加好,毕竟 Struts2 自己也是定义在 properties 属性文件中,而不是定义在自己的 xml 配置文件中。( Struts2 自带的 xml 配置文件为 struts-default.xml ,在 4.1 小节中已记述)。这里是为了让读者知道 struts.xml 配置文件也可以配置这些属性,因此写在 struts.xml 配置文件中。从 3.2 小节笔者说明 struts.xml 配置文件时并没有介绍 <constant> 标签这点也可以知道笔者个人其实是不赞同这样的配置手段即在 struts.xml 中配置 <constant> 标签。
在 <Action> 标签中配置“ result ”,和第 3 章类似,将这两个 JSP 文件的导航流程配置好即可。
( 4 )开始进行文件上传功能展示,按照如上记述的步骤执行即可。笔者在桌面上新建了两个文本文件,将它们上传到 JBoss 已部署的 Web 项目中展示文件上传的 upload 文件夹下。如图 4.11 所示。
其实还可以指定上传文件的格式,让它只上传特定类型的文件。比如只能上传文本和 xml 文件,则在 struts.xml 需要显示配置“ uploadFile ”拦截器。如下代码:
<!------------------------------------------- 文件名:struts.xml-------------------------------->
<struts>
<!-- Action 所在包定义 -->
<package name="C04.4" extends="struts-default">
<!-- Action 名字,类以及导航页面定义 -->
<!-- 通过Action 类处理才导航的的Action 定义 -->
<action name="upload" class="action.UploadAction">
<result name="input">/jsp/upload.jsp</result>
<result name="success">/jsp/result.jsp</result>
</action>
<!— 显示配置文件上传拦截器 -->
<interceptor-ref name=”fileUpload”>
<!— 指定特定类型的上传文件 -->
<param name =”allowedTypes”>text/plain,application/xml</param>
</ interceptor-ref >
<interceptor-ref name=”defaultStack”></ interceptor-ref >
</package>
</struts>
定义了一个名为“ allowedTypes ”的参数,其中在 <param></param> 之间的是文件类型,也可以用“,”间隔,表示允许上传多个文件类型。这里允许上传文件类型为 txt 、 xml 格式的文件。如果读者不知道各个文件类型的定义,可在自己的 JBoss 安装目录中的 server\default\deploy\jboss-web.deployer\conf\ 下的 web.xml 文件中找到(搜索 <mime-mapping> 即可)。
注意:如果显示配置 Struts2 自己的缺省拦截器一定要写在“ defaultStack ”前,否则“ fileUpload ”拦截器不会执行拦截。因为 Struts2 中如果某个拦截器执行拦截时候发现自己已经执行过,第二个乃至之后同名的拦截器都不会执行。这里因为“ defaultStack ”拦截器栈中包含了“ fileUpload ”拦截器,而“ fileUpload ”拦截器已经执行拦截了,则不会再执行拦截。如果把“ defaultStack ”拦截器栈放在“ fileUpload ”拦截器前配置,则只执行“ defaultStack ”拦截器栈中的“ fileUpload ”拦截器,这里是没有定义“ allowedTypes ”的, Struts2 缺省默认的是支持所有文件类型。因此它会支持所有文件类型的文件上传。因此再设定“ allowedTypes ”就没有任何意义了。
更多信息请查看 java进阶网 http://www.javady.com/index.php/category/thread