一、单文件上传
上传表单页面:select.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>上传表单页面</title>
</head>
<body>
<h3>Struts2基于表单的文件上传</h3>
<s:form action="upload" method="post" theme="simple" enctype="multipart/form-data">
输入账号:<s:textfield name="uid"/><br/><br/><!-- 文本 -->
选择头像:<s:file name="headImage" label="选择上传的文件"/><!-- 要上传的文件 -->
<s:submit value="提交"/>
<s:fielderror/>
</s:form>
</body>
</html>
如下所示的上传显示界面:
当文件上传页面提交请求时,请求发送到wq.action,这是一个Struts2的Action,该Action处理上传请求,具体的UploadAction类代码如下:
package cn.tedu.action;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import cn.tedu.web.BaseAction;
@Controller
@Scope("prototype")
public class UploadAction extends BaseAction{
private String uid; //账号
private File headImage; //上传的文件
private String headImageContentType;//文件类型
private String headImageFileName;//文件名
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public File getHeadImage() {
return headImage;
}
public void setHeadImage(File headImage) {
this.headImage = headImage;
}
public String getHeadImageContentType() {
return headImageContentType;
}
public void setHeadImageContentType(String headImageContentType) {
this.headImageContentType = headImageContentType;
}
public String getHeadImageFileName() {
return headImageFileName;
}
public void setHeadImageFileName(String headImageFileName) {
this.headImageFileName = headImageFileName;
}
//上传的时候调用
public String up(){
// 上传文件的保存位置在“/image”,该位置在tomcat服务器的“webapps”之中
String realpath= ServletActionContext.getServletContext().getRealPath("/image");
// 声明文件目录image,如果文件名不存在就建一个
File file = new File(realpath);
if(!file.exists()){
file.mkdirs();
}
//实现文件上传
try {
FileUtils.copyFile(headImage, new File(file, headImageFileName));
} catch (IOException e) {
e.printStackTrace();
}
return SUCCESS;
}
}
需要注意的是,上面的Action除了包含两个表单域的name属性外,还包含headImageContentType和headImageFileName两个属性,这两个属性分别能用于封装上传文件的文件类型、上传文件的文件名。可以这样认为:如果表单中包含一个name属性为xxx的文件域,则对应的Action需要使用3个属性来封装文件域信息:
- 类型为java.io.File的xxx属性来封装文件;
- 类型为String的xxxFileName属性封装了该文件域对应的文件名;
- 类型为String的xxxContentType属性封装了该文件域对应的文件类型。
所以,在Action的up方法中,可以直接通过这3个属性获取上传文件的文件、文件名、文件类型。
(3) 接下来进行UploadAction的配置(struts.xml文件配置),具体代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!--指定国际化资源文件(下一章会讲到)-->
<constant name="struts.custom.i18n.resources" value="messageResource"/>
<!--设置Struts应用的解码集-->
<constant name="struts.i18n.encoding" value="utf-8"/>
<package namespace="/" name="default" extends="struts-default">
<!-- 文件上传主页面 -->
<action name="wq">
<result>/select.jsp</result>
</action>
<action name="upload" class="uploadAction" method="up">
<result name="success">/uploadSuccess.jsp</result>
</action>
</package>
</struts>
由于是整合了spring,所以spring-web.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<!-- spring的组件扫描 -->
<context:component-scan base-package="cn.tedu"/>
</beans>
导包:
最后写一个上传成功页面(uploadSuccess.jsp)
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>上传成功页面</title>
</head>
<body>
<h3>上传成功</h3>
用户账号:<s:property value="uid"/><br/>
您的头像:<img src="<s:property value="'image/' + headImageFileName"/>" alt="图像无法显示"/>
</body>
</html>
上传成功后会显示上传的图片和用户账号
上传过程图:
1.选择图片
2.确认选择
3.提交之后,显示上传成功
上传的图片保存位置如下:
--------------------------------------------------------------------------------------------------------------
二、拦截器实现文件的过滤
Struts2提供了一个名为fileUpload拦截器,通过配置该拦截器可以轻松地实现文件过滤。为了让fileUpload拦截器起作用,只需要在处理文件上传的Action中配置该拦截器引用即可。
配置fileUpload拦截器时可以指定如下两个参数:
- allowTypes:该参数指定允许上传文件的类型,多个文件类型之间以英文逗号隔开;
- maximumSize:该参数指定允许上传文件的大小,单位是字节。
当文件过滤失败后,系统自动转入input逻辑视图,因此必须为Action配置名为input的逻辑视图。
(1) 通过拦截器来实现文件过滤的struts.xml配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!--指定国际化资源文件(下一章会讲到)-->
<constant name="struts.custom.i18n.resources" value="messageResource"/>
<!--设置Struts应用的解码集 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
<constant name="struts.i18n.encoding" value="utf-8"/>
<!-- 上传文件的总大小(可能上传多个)该属性指定Struts 2文件上传中整个请求内容允许的最大字节数
而拦截器中配置的是限制单个上传文件的大小-->
<constant name="struts.multipart.maxSize" value="1000000000"/>
<!--package中加入拦截器-->
<package namespace="/" name="default" extends="struts-default">
<interceptors>
<!--配置拦截器栈-->
<interceptor-stack name="myStack">
<!--配置fileUpload拦截器-->
<interceptor-ref name="fileUpload">
<!--配置允许上传文件的类型(此处要注意的是png图片在ie浏览器中是image/x-png类型)-->
<param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg,image/jpg,image/x-png,image/pjpeg</param>
<!--配置允许上传文件大小拦截器,单位是字节(2的16次幂=65536(64k))-->
<param name="maximumSize">65536</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!-- 拦截器配置完毕 -->
<!-- 文件上传主页面 -->
<action name="wq">
<result>/select.jsp</result>
</action>
<action name="upload" class="uploadAction" method="up">
<!-- 使用拦截器 -->
<interceptor-ref name="myStack"/>
<result name="success">/uploadSuccess.jsp</result>
<!--过滤失败,系统会转入input逻辑视图,这里配置其返回选择界面-->
<result name="input">/select.jsp</result>
</action>
</package>
</struts>
格式不对和容量大于64kb会上传失败,直接返回重新选择的界面。如果上传失败,系统需要回应上传失败信息。因此,需要在文件上传页select.jsp页面中加上“<s:filederror/>”------->(我直接加到了select.jsp代码中,你可以回看上面)
(a) 例如:文件格式不对
提交之后页面显示如下:
(b)文件大小超过了限额(本案例文件大小限制64KB)
提交之后页面显示如下:
-------------------------------------------------------------------------------------------------
三、文件上传的常量配置
上传文件时,系统默认使用web服务器的工作路径作为临时路径。为了避免文件上传时候使用Web服务器的工作路径作为临时路径,则应该设置struts.multipart.saveDir常量。该常量指定上传文件的临时保存路径。该常量配置示例如下:
<constant name="struts.multipart.saveDir" value="HOME/....(写上路径)..."/>
Struts2配置文件中的struts.multipart.saveDir起什么作用?
原来初步感觉这个文件夹就服务端保存上传文件的文件夹,不过根本不是这么回事!
这个文件夹只是用来保存上传文件的“临时路径”,文件上传完毕后就会从此路径移除。
如果不配置将使用默认的 javax.servlet.context.tempdir 来保存临时文件。
所以这个目录设不设无所谓
此外,还有一个文件上传的常量struts.multipart.maxSize。该常量指定struts.mutipart.maxSize。该常量指定在struts2文件上传中整个请求内容所允许的最大字节数,默认为2097152(即2MB)。该常量配置示例如下:
<constant name="struts.multipart.maxSize" value="209971520"/>
该属性是上传文件的总大小(可能上传多个),该属性指定Struts 2文件上传中整个请求内容允许的最大字节数,而拦截器中配置的是限制单个上传文件的大小
四、Struts2多文件上传
在Struts2应用中,如果一个页面有多个文件域需要实现上传,则可以为每个文件域提供三个属性,分别封装该文件域对应的文件名、文件类型和文件内容。多文件上传与单文件上传没有什么区别,仅仅是利用数组同时上传多个文件的方式。在处理多文件上传时,要注意改变的是,在Action类中,需要使用三个数组分别封装文件名、文件类型和文件内容。
struts.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!--指定国际化资源文件(下一章会讲到)-->
<constant name="struts.custom.i18n.resources" value="messageResource"/>
<!--设置Struts应用的解码集 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
<constant name="struts.i18n.encoding" value="utf-8"/>
<!-- 上传文件的总大小(可能上传多个)该属性指定Struts 2文件上传中整个请求内容允许的最大字节数
而拦截器中配置的是限制单个上传文件的大小-->
<constant name="struts.multipart.maxSize" value="1000000000"/>
<!--package中加入拦截器-->
<package namespace="/" name="default" extends="struts-default">
<interceptors>
<!--配置拦截器栈-->
<interceptor-stack name="myStack">
<!--配置fileUpload拦截器-->
<interceptor-ref name="fileUpload">
<!--配置允许上传文件的类型(此处要注意的是png图片在ie浏览器中是image/x-png类型)-->
<param name="allowedTypes">image/x-png,image/bmp,image/gif,image/jpeg,image/jpg</param>
<!--配置允许上传文件大小拦截器,单位是字节(2的16次幂=65536(64k))-->
<param name="maximumSize">65536</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!-- 拦截器配置完毕 -->
<!-- 多文件上传 -->
<!-- 文件上传主页面 -->
<action name="wq1">
<result>/select1.jsp</result>
</action>
<action name="upload1" class="uploadAction1" method="up">
<!-- 使用拦截器 -->
<interceptor-ref name="myStack"/>
<result name="success">/uploadSuccess1.jsp</result>
<!--过滤失败,系统会转入input逻辑视图,这里配置其返回选择界面-->
<result name="input">/select1.jsp</result>
</action>
</package>
</struts>
多文件上传显示页面:
代码如下:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>上传表单页面</title>
</head>
<body>
<h3>Struts2基于表单的多文件上传</h3>
<s:form action="upload1" method="post" theme="simple" enctype="multipart/form-data">
输入账号:<s:textfield name="uid"/><br/><br/><!-- 文本 -->
多个头像1:<s:file name="headImage" label="选择上传的文件"/><br/><br/><!-- 要上传的文件 -->
多个头像2:<s:file name="headImage" label="选择上传的文件"/><br/><br/><!-- 要上传的文件 -->
<s:submit value="提交"/>
<s:fielderror/>
</s:form>
</body>
</html>
控制器UploadAction:
package cn.tedu.action;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import cn.tedu.web.BaseAction;
@Controller
@Scope("prototype")
public class UploadAction1 extends BaseAction{
private String uid; //账号
private List<File> headImage; //上传的文件
private List<String> headImageContentType;//文件类型
private List<String> headImageFileName;//文件名
private String savePath;//保存路径
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public List<File> getHeadImage() {
return headImage;
}
public void setHeadImage(List<File> headImage) {
this.headImage = headImage;
}
public List<String> getHeadImageContentType() {
return headImageContentType;
}
public void setHeadImageContentType(List<String> headImageContentType) {
this.headImageContentType = headImageContentType;
}
public List<String> getHeadImageFileName() {
return headImageFileName;
}
public void setHeadImageFileName(List<String> headImageFileName) {
this.headImageFileName = headImageFileName;
}
public String getSavePath() {
return savePath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
//上传的时候调用
public String up(){
savePath = "moreImage";
String realPath = ServletActionContext.getServletContext().getRealPath("/" + savePath);
// 上传文件的保存位置在“/moreImage”,该位置在tomcat服务器的“webapps”之中
// 声明文件目录moreImage,如果文件名不存在就建一个
File file = new File(realPath);
if(!file.exists()){
file.mkdirs();
}
//实现文件上传
try {
for(int i = 0; i< headImage.size(); i++){
FileUtils.copyFile(headImage.get(i), new File(file, headImageFileName.get(i)));
}
} catch (IOException e) {
e.printStackTrace();
}
return SUCCESS;
}
}
上传成功页面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>上传成功页面</title>
</head>
<body>
<h3>上传成功</h3>
用户账号:<s:property value="uid"/><br/>
文件路径:<s:property value="savePath"/><br>
<!--
根据上传文件的文件名,在页面上显示上传的图片 采用相对路径,不要使用绝对路径
在Action中得到了上传文件的目录savePath,若没有目录
ServletActionContext.getServletContext().getRealPath("");
则在该页面中直接使用<s:property />作为img的相对路径
img中采用了EL表达式 并结合struts标签完成路径的拼接,
<s:property />表示headImageFileName集合中的每一个文件名,即每一个元素
-->
文件为:<s:property value="headImageFileName"/><br>
----------遍历文件:----------<br>
<s:iterator value="headImageFileName">
<img src="${savePath}/<s:property /> "/>
</s:iterator>
</body>
</html>
选择上传文件:
上传成功:
注意:文件图片在显示的时候,img标签建议采用相对路径