在Struts2中,上传任意多个文件也非常容易实现。首先,要想上传任意多个文件,需要在客户端使用DOM技术生成任意多个<input type=”file” />标签。name属性值都相同。multiUpload.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>上传多个文件</title>
<script language="javascript">
function addComponent()
{
var uploadHTML = document.createElement( "<input type='file' name='upload'>");
document.getElementById("files").appendChild(uploadHTML);
uploadHTML = document.createElement( "<p/>");
document.getElementById("files").appendChild(uploadHTML);
}
</script>
</head>
<body>
<input type="button" onclick="addComponent();" value="添加文件" />
<br />
<s:actionerror />
<form onsubmit="return true;" action="multiUpload.action" method="post"
enctype="multipart/form-data"><span id="files"> <input
type='file' name='upload' />
<p />
</span> <input type="submit" value="上传" /></form>
</body>
</html>
这里为了方便起见,我们直接使用原始的HTML表单,大家可以把这个可以上传任意多个文件的JSP页面和上面单文件上传的JSP页面做对比。上面的javascript代码可以生成任意多个<input type=’file’>标签,name的值都为upload。至于Action类,和上传单个文件的Action类基本一致,只需要将三个属性的类型改为数组或者List即可。
用数组实现的代码如下:
package org.leno.struts2.action;
import java.io.*;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class MultiUploadAction extends ActionSupport {
private static final long serialVersionUID =
// 代表上传文件的File对象
private File[] upload;
// 上传文件名
private String[] uploadFileName;
// 上传文件的MIME类型
private String[] uploadContentType;
// 保存上传文件的目录,相对于WEB应用程序的根路径,在struts.xml中配置
private String uploadDir;
public File[] getUpload() {
return upload;
}
public void setUpload(File[] upload) {
this.upload = upload;
}
public String[] getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String[] uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String[] getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String[] uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
@Override
public String execute() throws Exception {
String newFileName = null;
File dir = new File(ServletActionContext.getServletContext()
.getRealPath(uploadDir));
// 如果该目录不存在,就创建
if (!dir.exists()) {
dir.mkdirs();
}
for (int i = 0; i < upload.length; i++) {
// 得到当前时间自
long now = System.currentTimeMillis();
// 得到保存上传文件的目录的真实路径
// 为避免重名文件覆盖,判断上传文件是否有扩展名,以时间戳作为新的文件名
int index = uploadFileName[i].lastIndexOf(".");
if (index != -1) {
newFileName = now + uploadFileName[i].substring(index);
} else {
newFileName = Long.toString(now);
}
// 读取保存在临时目录下的上传文件,写入到新的文件中
InputStream is = new FileInputStream(upload[i]);
OutputStream os = new FileOutputStream(new File(dir, newFileName));
byte[] buf = new byte[1024];
int len = -1;
while ((len = is.read(buf)) != -1) {
os.write(buf, 0, len);
}
is.close();
os.close();
}
return SUCCESS;
}
}
用List实现的代码如下:
package org.leno.struts2.action;
import java.io.*;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class MultiUploadAction2 extends ActionSupport {
private static final long serialVersionUID =
// 代表上传文件的File对象
private List<File> upload;
// 上传文件名
private List<String> uploadFileName;
// 上传文件的MIME类型
private List<String> uploadContentType;
// 保存上传文件的目录,相对于WEB应用程序的根路径,在struts.xml中配置
private String uploadDir;
public List<File> getUpload() {
return upload;
}
public void setUpload(List<File> upload) {
this.upload = upload;
}
public List<String> getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(List<String> uploadFileName) {
this.uploadFileName = uploadFileName;
}
public List<String> getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(List<String> uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
@Override
public String execute() throws Exception {
String newFileName = null;
File dir = new File(ServletActionContext.getServletContext()
.getRealPath(uploadDir));
// 如果该目录不存在,就创建
if (!dir.exists()) {
dir.mkdirs();
}
for (int i = 0; i < upload.size(); i++) {
// 得到当前时间自
long now = System.currentTimeMillis();
// 得到保存上传文件的目录的真实路径
// 为避免重名文件覆盖,判断上传文件是否有扩展名,以时间戳作为新的文件名
int index = uploadFileName.get(i).lastIndexOf(".");
if (index != -1) {
newFileName = now + uploadFileName.get(i).substring(index);
} else {
newFileName = Long.toString(now);
}
// 读取保存在临时目录下的上传文件,写入到新的文件中
InputStream is = new FileInputStream(upload.get(i));
OutputStream os = new FileOutputStream(new File(dir, newFileName));
byte[] buf = new byte[1024];
int len = -1;
while ((len = is.read(buf)) != -1) {
os.write(buf, 0, len);
}
is.close();
os.close();
}
return SUCCESS;
}
}
我们看到,数组和List的使用基本上大同小异。以List为例,在execute方法中,只是对List对象进行枚举,在循环中的代码和上传单个文件时的代码基本相同。如果读者使用过struts1.x的上传组件,是不是感觉Struts2的上传功能更容易实现呢?在Struts1.x中上传多个文件时,可是需要建立带索引的属性的。而在Struts2中,就是这么简单就搞定了。呵呵,当然啦,我们还有点额外的事情要做:
在struts.xml上面添加一个处理多文件上传的Action:
<action name="multiUpload"
class="org.leno.struts2.action.MultiUploadAction">
<result name="success">/multiSuccess.jsp</result>
<result name="input">/multiUpload.jsp</result>
<param name="uploadDir">/WEB-INF/UploadFiles</param>
</action>
添加批量上传成功后的页面multiSuccess.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>批量上传成功,文件信息如下:</h1>
文件名:<s:property value="uploadFileName" /><br/>
文件类型:<s:property value="uploadContentType" /><br/>
</body>
</html>
下图是上传任意多个文件的界面:
现在,咱们就学会了用struts2实现任意多个文件上传的功能,又掌握了一项技能,是不是很有成就感呢?呵呵,让我们继续吧!