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

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

    文件上传页面和显示上传成功页面代码内容。
    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”就没有任何意义了。

附件下载:http://dl.iteye.com/topics/download/45b325fd-945a-3946-813c-b75e265b6620

评论 共 7 条 请登录后发表评论
7 楼 fangfumin 2011-07-25 10:25
请问下楼主,我想传的文件在100m以上。有没有方法?你这种方法好像不支持
6 楼 enjoy2010 2010-11-18 14:07
不错,不错!赞一个
5 楼 z276356445t 2010-09-15 21:00
赞楼主一个,一直都想学struts的上传机制,但是一直都没有找到好的例子,今天弄了3个小时,终于把这个上传的基础问题给解决了,谢谢!
4 楼 blue3377 2010-03-25 10:35
很好.
FileUtils.copyFile(files.get(i), target); 这些怎么用?
3 楼 wenxiang_tune 2009-10-25 14:55
很好!
2 楼 黑暗浪子 2009-10-19 09:43
release 写道
commons.io包里有现成方法
FileUtils.copyFile(files.get(i), target);

thanks
1 楼 release 2009-10-17 16:48
commons.io包里有现成方法
FileUtils.copyFile(files.get(i), target);

发表评论

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

文章信息

Global site tag (gtag.js) - Google Analytics