Struts2 文件上传和多文件上传

   下面开始将讲解Struts2的文件上传功能,使用Struts2实现文件上传比起使用Servlet进行上传,简单了很多,具体表现在使用Struts2进行文件上传时,不需要在写代码来解析request来得到List<FileItem>,而是直接在Action中定义对应的名字java.io.File类型的成员变量(存放的是临时文件),String类型的 表单名字ContentType(用来接收上传的文件类型),String类型的 表单名字FileName(用来接收上传文件的名字),关于Struts2中是如何把这些变量获取到的,我还没有看代码,目前的猜测是通过反射的机制获取的。

在学习Struts2文件上传之前需要先了解下核心jar包(struts2-core.jar)下的default.properties配置文件,是Struts2中的默认配置管理器,该配置文件中主要存放了一些工程的配置参数信息,比如请求名的后缀、工程国际化编码、文件上传大小的限定等。

首先说下Struts2进行文件上传的业务流程:

JSP界面数据通过http协议传送到服务器端的request对象中——>Struts2使用common-io.jar和file-upload对request进行解析,将对应的长传文件暂时保存在临时文件目录中,同时将对应的数据赋值给Action中的成员变量(临时文件、文件名、文件类型等)——>通过Action中的文件复制方法将临时文件复制到用户指定的目录下——>返回给前台提示信息(文件上传成功

 

下面开始创建一个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" class="com.upload.action.UploadAction">
<result name="success">/fileUploadSuccess.jsp</result>
</action>
<!-- 多个文件上传Action -->
<action name="multiUpload" class="com.upload.action.MultiUploadAction">
<result name="success">/multifileUploadSuccess.jsp</result>
</action>
</package>
<!-- 对可上传的文件大小进行限制 -->
<constant name="struts.multipart.maxSize" 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,但是这样貌似行不通,服务器还是会报错,不知道是我配置的有问题还是什么原因,希望知道原因的同行告知我们,谢谢!

猜你喜欢

转载自youcp999.iteye.com/blog/2321461