Struts2文件上传和多文件上传
?
下面开始创建一个Struts2文件上传的实例,新建web工程,导入jar包,配置web.xml文件,写jsp界面,写Action,在struts.xml配置文件中进行配置。
工程结构图如下:
第一步:新建web工程,fileUploadStruts2,导入jar包;
第二步:写配置文件web.xml,配置代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
</web-app>
第三步:写界面,我这里为了同时演示单个文件上传和多个文件上传,所以就写了四个页面,下面页面的代码,都很简单,基本都是一些简单的input表单输入框,只有文件上传成功页面用到了ognl表达式。界面名字和内容如下:
单个文件上传页面:fileUpload.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>fileUpload</title>
</head>
<body>
<h3>文件上传Demo</h3>
<form action="/fileUploadStruts2/upload/upload.action" method="post" enctype="multipart/form-data">
名字:<input type="text" name="name"><br>
file:<input type="file" name="file"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
单个文件上传成功页面:fileUploadSuccess.jsp
<%@ page language="java" import="java.util.*" isELIgnored="false" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>文件上传成功</title>
</head>
<body>
名字:${requestScope.name }<br/>
<s:property value="fileFileName.toUpperCase()"/>
fileName:${requestScope.fileFileName }<br/>
fileType:${requestScope.fileContentType }
</body>
</html>
?
多文件上传页面:multifileUpload.jsp(如果表单中文件名字一样,那么后台需要使用数组或者List<File>集合来接收多个文件,当然如果input的name不同,那么需要多个File类型的成员变量来接收对应的文件)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>fileUpload</title>
</head>
<body>
<h3>多文件上传Demo</h3>
<form action="/fileUploadStruts2/upload/multiUpload.action" method="post" enctype="multipart/form-data">
名字:<input type="text" name="name"><br>
file1:<input type="file" name="file"><br>
file2:<input type="file" name="file"><br>
file3:<input type="file" name="file"><br>
<br/>
file4:<input type="file" name="file2"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
?
多个文件上传成功的提示:multifileUpload.jsp
<%@ page language="java" import="java.util.*" isELIgnored="false" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>文件上传成功</title>
</head>
<body>
名字:${requestScope.name }<br/>
<s:iterator value="fileFileName" id="f" status="status">
文件${status.count }的文件名:<s:property value="#f"/><br/>
</s:iterator>
<s:iterator value="fileContentType" var="f" status="status">
文件${status.count }类型<s:property value="#f"/><br>
</s:iterator>
file2文件名<s:property value="#request.file2FileName"/><br>
file2类型<s:property value="#request.file2ContentType"/>
</body>
</html>
第四步:写后台的业务处理逻辑Action
单个文件上传的Action:UploadAction.java
package com.upload.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* Struts2文件上传Action
* @author XiaoYun 2013-07-24
*/
public class UploadAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 3692768413857131416L;
private String name;
private File file;
// 文件名值和文件属性的写法是固定的:文件名FileName,文件名ContentType
private String fileFileName; // 这个是真实的文件名
private String fileContentType; // 真实的文件类型
@Override
public String execute() throws Exception {
// 获取文件上传的路径
String path = ServletActionContext.getServletContext().getRealPath("/upload");
// 将临时文件复制到指定的path目录
File descFile = new File(path, fileFileName);
OutputStream os = new FileOutputStream(descFile);
InputStream in = new FileInputStream(file);
byte[] buf = new byte[512];
int length = 0;
while((length = in.read(buf)) != -1) {
os.write(buf, 0, length);
}
os.close();
in.close();
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getFileFileName() {
return fileFileName;
}
public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
}
public String getFileContentType() {
return fileContentType;
}
public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
}
}
多个文件上传后台处理的Action:MultiUploadAction.java
package com.upload.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* 多文件上传Action
*
* @author XiaoYun 2013-07-25
*/
public class MultiUploadAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = -4807404517419569650L;
private String name;
private File[] file;
private String[] fileFileName;
private List<String> fileContentType;
private File file2;
private String file2FileName;
private String file2ContentType;
@Override
public String execute() throws Exception {
String path = ServletActionContext.getServletContext().getRealPath("/upload");
int size = file.length;
System.out.println(size);
// 复制封装的多个文件
for (int i = 0; i < size; i++) {
System.out.println("hello");
this.copy(file[i], fileFileName[i], path);
}
// 复制单个文件
//this.copy(file2, file2FileName, path);
return SUCCESS;
}
/**
* 文件复制工具类
* @param file 文件
* @param fileFileName 文件名
* @param path 保存的目录
* @throws Exception
*/
private void copy(File file, String fileFileName, String path) throws Exception {
// 实例化一个文件输入流
InputStream is = new FileInputStream(file);
// 实例化一个文件输出流
OutputStream os = new FileOutputStream(new File(path, fileFileName));
byte[] buf = new byte[512];
int len = 0;
while ((len = is.read(buf)) != -1) {
os.write(buf, 0, len);
}
// 关闭输入流和输出流
os.close();
is.close();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public File[] getFile() {
return file;
}
public void setFile(File[] file) {
this.file = file;
}
public String[] getFileFileName() {
return fileFileName;
}
public void setFileFileName(String[] fileFileName) {
this.fileFileName = fileFileName;
}
public List<String> getFileContentType() {
return fileContentType;
}
public void setFileContentType(List<String> fileContentType) {
this.fileContentType = fileContentType;
}
public File getFile2() {
return file2;
}
public void setFile2(File file2) {
this.file2 = file2;
}
public String getFile2FileName() {
return file2FileName;
}
public void setFile2FileName(String file2FileName) {
this.file2FileName = file2FileName;
}
public String getFile2ContentType() {
return file2ContentType;
}
public void setFile2ContentType(String file2ContentType) {
this.file2ContentType = file2ContentType;
}
}
第五步,在struts.xml文件中进行配置,配置文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="upload" extends="struts-default" namespace="/upload">
<!-- 普通的文件上传Action -->
<action name="upload" value="200097152"/>
</struts>
第六步,同步修改tomcat的配置文件(我的版本是tomcat5.5,没有在别的tomcat版本上进行测试),
打开tomcat安装目录\conf\server.xml,在</Host>前面加上<Context path="/fileUploadStruts2(你的工程名字)" docBase="D:\Workspaces\study\fileUploadStruts2\WebRoot(你的WebRoot目录的绝对路径)" reloadable="true"/>。
?
接着启动将该工程部署到tomcat上,我的JDK是1.6,关于对文件格式和非空的校验我没有做,如果你在实际应用的用到了,就自己在前台和后台进行校验,我不在多写了,思路是可以对文件名以最后一个“.”为隔断进行截断,然后将“.”后面的字符串与给定格式进行比较。工程可以正常运行,在我的机器上能够正确跑通,如果大家要是跑不通或者在任何地方有疑问,都可以给我留言。当然也欢迎各位同行和前辈对我的博客不合理的地方进行批评指正,谢谢。
??? 上传文件的实现方式主要是通过struts2中的FileUploadInteceptor拦截器实现的,关于上传文件的大小在struts.properties中配置还是在struts.xml中配置的问题,我想进行下说明,我进行了试验,如果是在struts.properties和struts.xml中都配置了上传文件的大小,事实证明struts.properties的优先级要高于struts.xml。如果你想在灵活的控制单个Action中上传文件的大小,可以在Action中根据file.length()来控制文件的长度。(不错理论上说也可以为对应的Action加上FileUpload拦截器,并在interceptor中配置maximumSize,但是这样貌似行不通,服务器还是会报错,不知道是我配置的有问题还是什么原因,希望知道原因的同行告知我们,谢谢!)
?
?
???
?