只有当表单的method为post,并且enctype要设置为multipart/form-data时,本地的二进制文件才能够上传到服务器。Struts2本身并不会去解析multipart/form-data,而是需要借助其他框架,所以它的上传功能需要依赖Common-FileUpload、COS等组件。相应的,我们需要把commons-io包跟commons-fileupload包添加到项目中。Struts2对原有的上传解析器做了进一步的封装,使用起来更加简便。


实现文件上传的action

Struts2使用File类型来封装文件域,因此处理action类中应有一个File类型的属性。除此之外,还应该包括uploadFileName和uploadContentType这两个属性,用于封装上传文件的文件名,文件类型。由此我们可以看到,文件的内容由File封装,而文件的参数(文件名,文件类型)由另外两个成员变量封装。这三个成员变量是实现文件上传的编程关键。假设说上传组件的name是upload,那么action中与这个文件相关的三个属性如下:

private File upload;

private String cuploadFileName;

private String uploadContentType;


upload.java的代码如下:

public class upload extends ActionSupport {
	
	private File upload;
	private String uploadContentType;
	private String uploadFileName;
	private String title;

	private String savePath;
	
	public String getSavePath() {
		return ServletActionContext.getServletContext().getRealPath(savePath);
	}
	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}
		
	@Override
	public String execute() throws Exception {
		System.out.println(getSavePath());
		FileOutputStream fos=new FileOutputStream(getSavePath()+"\\"+getUploadFileName());
		FileInputStream fis=new FileInputStream(getUpload());
		
		byte[] buffer=new byte[1024];
		int len=0;
		while((len=fis.read(buffer))>0)
		{
			fos.write(buffer,0,len);
		}
			
		// TODO Auto-generated method stub
		return SUCCESS;
	}
		
}

代码中省略了一些成员变量的set与get方法。要注意savaPath的get方法比较特殊,返回值需要特别注意!引包的时候需要注意io接口是java.io。

------------------------------------------------------------------------------------------

提交表单的写法如下:

<s:form action="lalala/upload" enctype="multipart/form-data" method="post">
<s:textfield name="title" label="title" />
<s:file  name="upload" label="choose file"/>

<s:submit value="submit"/>

</s:form>

这里需要注意表单的方法必须是post,必须设置enctype属性。

--------------------------------------------------------------------------------------------

显示图片的jsp页面的写法:

title:<s:property value=" title" /><br /> 
file is:<img src="<s:property value="'/z001/uploadFiles/'+uploadFileName"/>" /><br />

这里要额外注意图片的src要带上项目名称。教材中没有写,可是我在测试的时候回报错。

-------------------------------------------------------------------------------------------

文件结构系统如下图所示:

wKiom1XVSrTARPz7AAFZ62pUwJI748.jpg

其中要额外注意uploadFiles的位置。另外,upload.class中的savePath属性是由struts.xml文件指定的。


手动实现文件过滤

由于web应用不希望用户没有节制,不按规定上传文件,因此应用有必要对上传的文件类型,文件大小进行过滤。如果需要手动实现文件过滤,那么可以按照如下步骤进行

  1. 在Action中定义一个专门用于进行文件过滤的方法,名字任意,只负责上传文件是否为允许类型。若想动态地设置合法的文件类型,只需要在这个action中定义合法类型字符串(一系列合法类型用,分隔),然后在xml中动态配置。再利用方法中的validate方法为所有处理逻辑验证文件类型。

  2. 通过手动输入校验来检查文件名

  3. 通过File类型的length方法获得文件大小,以判断大小是否合法。


拦截器实现文件过滤

        Struts2提供了一个文件上传的拦截器——fileUpload,所以我们只需要配置拦截器就可以轻松实现文件上传的拦截过滤。这个拦截器是对应特定action的,所以应该用interceptor-ref标签在action元素下配置。配置的时候我们能够制定两个param参数,分别是allowedTypes和maximumSize。过滤失败自动跳转到逻辑视图为input的页面。

       当使用此拦截器来过滤文件大小,文件内容时,必须显示地配置引用Struts默认的拦截器栈——defaultStack,并且fileUpload要在defaultStack之前配置。

<interceptor-ref name="fileUpload">
	<param name="allowedTypes">p_w_picpath/png.p_w_picpath/gif,p_w_picpath/jpeg</param>
	<param name="maximumSize">2000</param>
</interceptor-ref>

<result name="input">/exception.jsp</result>
	
<interceptor-ref name="defaultStack"/>


输出错误提示

struts2的标签可以自动显示上传错误的信息,可也以使用<s:fielderror/>来显式地输出。若想国际化地输出错误信息,则需要配置国际化资源文件。上传文件太大的提示信息的key是struts.messages.error.file.too.large。上传类型不允许的key是struts.messages.error.content.type.not.allowed。


文件上传的常量配置

可以使用struts.multipart.saveDir常量来指定上传的时候的临时文件夹。