struts-fileupload.xml
<struts> <constant name="struts.configuration.xml.reload" value="true"></constant> <!-- 限制了一次上传文件总数最大为10M,默认为2M 当单个文件或文件数组和大小大于2Mb时,会抛出org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (2667603) exceeds the configured maximum (2097152) --> <constant name="struts.multipart.maxSize" value="10701096"></constant> <package name="upload" namespace="/upload" extends="struts-default"> <action name="one" class="edu.action.OneFileUploadAction" method="singleFile"> <result name="onemessage">/page/uploadmessage.jsp</result> </action> <action name="many" class="edu.action.ManyFileUpload" method="manyFile"> <result name="manymessage">/page/manyfilemessage.jsp</result> </action> </package> </struts>
OneFileUploadAction.java
package edu.action; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; public class OneFileUploadAction { private String userName; private File image; private String imageFileName; private String imageContentType; public String singleFile() throws IOException { //将文件保存在/image/下,得到文件的真实路径 String realPath = ServletActionContext.getServletContext().getRealPath("/image"); if (image!=null) { //得到上传文件路径 File imageFile = new File(new File(realPath),imageFileName); if (!imageFile.getParentFile().exists()) { imageFile.getParentFile().mkdirs(); //包含多级目录创建 } //struts在执行下句之前,会将上传的文件放进临时目录下,执行下句后,将临时文件copy进真实目录下后,会remove掉临时文件 FileUtils.copyFile(image, imageFile); ActionContext.getContext().put("message", "上传成功!"); //测试二进制数据下userName属性是否乱码 System.out.println("上传者:"+userName+",文件名:"+imageFileName+",文件类型:"+imageContentType+",状态:上传成功"); } return "onemessage"; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getImageFileName() { return imageFileName; } //文件名定义格式"File名+FileName" public void setImageFileName(String imageFileName) { this.imageFileName = imageFileName; } //与表单的<input type="file" name="image">属性名相同 public void setImage(File image) { this.image = image; } //文件类型名称定义格式"File名+ContentType" public void setImageContentType(String imageContentType) { this.imageContentType = imageContentType; } }上传成功后,控制台打印: 上传者:肖华,文件名:2012_03130103.JPG,文件类型:image/jpeg,状态:上传成功
OneFileUpload.jsp
<body> <form action="${pageContext.request.contextPath}/upload/one" enctype="multipart/form-data" method="post"> 姓名:<input type="text" name="userName"><br/> 照片:<input type="file" name="image"><br/> <input type="submit" value="regist"> </form> </body>
uploadmessage.jsp
<body> ${userName}:${imageFileName}:${message} </body>
总结:
第一步:在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。这两个文件可以从http://commons.apache.org/下载。
第二步:把form表的enctype设置为:“multipart/form-data“,如下:
<form action="${pageContext.request.contextPath}/upload/one"enctype="multipart/form-data" method="post">第三步:在Action类中添加以下属性,属性红色部分对应于表单中文件字段的名称,属性蓝色部分是固定格式:
public class HelloWorldAction{
private File uploadImage;//得到上传的文件
private String uploadImageContentType;//得到文件的类型
private String uploadImageFileName;//得到文件的名称
//这里略省了属性的getter/setter方法,提供了setter方法后,struts2会自动调用setter方法,为其赋值
}
注意:(1)struts默认一次性最大文件上传大小为2Mb,所以如果单个文件或文件数组之和大小大于2Mb的话,会抛出:org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (2667603) exceeds the configured maximum (2097152)
所以应该在struts.xml文件中配置常量控制文件上传最大大小。
<constant name="struts.multipart.maxSize" value="10701096"></constant>
(2)如果/image文件下存在同名的文件,则后者将覆盖前者,而不会报告任何错误。
(3)struts2对表单的中文乱码处理的很好,以及对enctype="multipart/form-data"表单中字符处理的很好,无需程序员手工处理!
2. 多文件上传:ManyFileUploadAction.java
ManyFileUploadAction.java
package edu.action; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; public class ManyFileUploadAction { private String userName; private File[] image; //这里可以使用List或数组保存 private String[] imageFileName;//这里可以使用List或数组保存 public String manyFile() throws IOException { //将文件保存在/image/下,得到文件的真实路径 String realPath = ServletActionContext.getServletContext().getRealPath("/image"); if (image!=null) { //得到上传文件目录 File imageDir = new File(realPath); if (!imageDir.exists()) { imageDir.mkdirs(); //包含多级目录创建 } for (int i = 0; i < image.length; i++) { File imageFile = new File(imageDir,imageFileName[i]); FileUtils.copyFile(image[i], imageFile); } ActionContext.getContext().put("count", image.length); } return "manymessage"; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String[] getImageFileName() { return imageFileName; } public void setImageFileName(String[] imageFileName) { this.imageFileName = imageFileName; } public void setImage(File[] image) { this.image = image; } }
<body> <form action="${pageContext.request.contextPath}/upload/many" enctype="multipart/form-data" method="post"> 姓名:<input type="text" name="userName"><br/> 照片1:<input type="file" name="image"><br/> 照片2:<input type="file" name="image"><br/> 照片3:<input type="file" name="image"><br/> <input type="submit" value="regist"> </form> </body>
<body> 用户名:${userName},照片个数:${count}<br> <c:forEach var="imageName" items="${imageFileName}"> ${imageName}:<img src="${pageContext.request.contextPath}/image/${imageName}" weight="200px" height="200px"/><br/> </c:forEach> </body>
浏览器:
点击regist按钮:
这里对于
<img src="${pageContext.request.contextPath}/image/${imageName}" weight="200px" height="200px"/>
如果文件名包含中文时,则无法显示,不知道为什么??
总结:
(1)对于多文件上传时,文件文本框的name属性须相同,在Action中多个文件,可以用数组和List集合保存。
(2)没有上传文件的文件文本框,struts2不会将其传给struts的Action,从上面的length=2可以看出。