为了能上传文件,必须将表单的method设置为post,将enctype设置为multipart/form-data。只有在这种情况下,浏览器才会把用户选择文件的二进制数据发送给服务器。Struts2不会自己去处理multipart/form-data的请求,需要调用其他上传框架来解析二进制请求数据。
struts.properties中:
#指定使用COS的文件上传解析器
#struts.multipart.parser=cos
#指定使用Pell的文件上传解析器
#struts.multipart.parser=pell
#Struts2默认使用Jakarta的Common-FileUpload的文件上传解析器
struts.multipart.parser=jakarta
由于Struts2默认使用Jakarta的Common-FileUpload的文件上传解析器,所以需要在web应用中增加两个JAR文件,commons-io-2.2.jar和commons-fileupload-1.3.1.jar,如果想使用其他的上传解析器,只需更改配置文件然后在添加相应的jar包即可。
接下来就简单写下文件上传的实现代码。
1.表单页面。
<%@ pagelanguage="java" import="java.util.*"pageEncoding="UTF-8"%>
<%@ taglibprefix="s" uri="/struts-tags"%>
<html>
<head>
<title>简单的文件上传</title>
</head>
<body>
<s:from action="upload" enctype="multipart/form-data">
<s:textfield name="title" label="文件标题"/>
<s:file name="upload" label="选择文件"/>
<s:submit value="上传"/>
</s:form>
</body>
</html>
2.处理上传请求的Action类。
public class UploadAction extends ActionSupport{
//封装文件标题的成员变量
private String title;
//封装上传文件域的成员变量
private File upload;
//封装上传文件类型的成员变量
private String uploadContentType;
//封装上传文件名的成员变量
private String uploadFileName;
//直接在struts.xml文件中配置的成员变量
private String savePath;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title= title;
}
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload= upload;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType= uploadContentType;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName= uploadFileName;
}
//获取上传文件保存的位置
@SuppressWarnings("unused")
private String getSavePath() throws Exception{
return ServletActionContext.getServletContext().getRealPath(savePath);
}
public void setSavePath(String savePath) {
this.savePath= savePath;
}
@Override
public String execute() throws Exception{
//以服务器的文件保存地址和原文件名建立上传文件输出流
FileOutputStream fos=new FileOutputStream(getSavePath()+"\\"+getUploadFileName());
FileInputStream fis=new FileInputStream(getUpload());
byte[] buffer=new byte[1024];
int len=0;
while((len=fis.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fis.close();
fos.close();
return SUCCESS;
}
}
值得注意的是,File属性无法获取上传文件的文件名和文件类型,所以Struts2直接将文件域中包含的上传文件名和文件类型的信息封装到uploadFileName和uploadContentType成员变量中,通过getter方法即可获取。
3.在struts.xml中配置
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="neuq" namespace="/" extends="struts-default">
<global-results>
<result name="ok">/ok.jsp</result>
<result name="failure">/failure.jsp</result>
</global-results>
<action name="upload" class="cn.neuq.action.UploadAction">
<!--动态设置Action的属性值--!>
<param name="savePath">/uploadFiles</param>
<result>/index.jsp</result>
</action>
</package>
</struts>
至此,文件上传完成,当然,还可以实现文件过滤。
1.手动实现文件过滤
在Action中定义一个用于文件过滤的方法。
public String filterTypes(String[] types){
//获取上传的文件类型
String fileType=getUploadContentType();
for(String type:types){
if(type.equals(fileType)){
return null;
}
}
return ERROR;
}
为了让程序动态配置允许上传的文件列表,需要为该Action增加一个allowTypes属性,并添加setter和getter方法。
Action中执行校验的validate方法
public void validate(){
//判断当前类型是否允许上传
String filterResult=filterTypes(getAllowTypes().split(","));
if(filterResult!=null){
//添加FiledError
addFieldError("upload","您要上传的文件类型不正确");
}
}
在struts.xml中进行配置
<action name="upload" class="cn.neuq.action.UploadAction">
<!--动态设置Action的属性值--!>
<param name="savePath">/uploadFiles</param>
<!--设置允许上传的文件类型-->
<param name="allowTypes">image/png,image/gif,image/jpeg</param>
<!--FieldError需要配置input视图--!>
<result name="input">/upload.jsp</result>
<result>/index.jsp</result>
</action>
2.拦截器实现文件过滤
Struts2中文件上传的拦截器是fileUpload,只需在struts.xml中配置即可使用此拦截器。
<action name="upload" class="cn.neuq.action.UploadAction">
<interceptor-ref name="fileUpload">
<!--配置允许上传的文件类型--!>
<param name="allowedTypes">image/png,image/gif,image/jpeg</param>
<!--配置允许上传的文件大小-->
<param name="maximumSize">2000</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<!--动态设置Action的属性值--!>
<param name="savePath">/uploadFiles</param>
<result name="input">/upload.jsp</result>
<result>/index.jsp</result>
</action>
另外,Struts2执行文件上传过程中,需要指定一个临时文件夹,如果没有指定,系统默认javax.servlet.context.tempdir,在Tomcat安装路径下的work\Catalina\localhost\路径下。如果不想使用Tomcat工作路径作为临时路径,可设置struts.multipart.saveDir常量来控制。该常量可通过struts.xml或struts.properties来设置。