文件上传是WEB应用经常需要面对的问题。在大部分时候,用户的请求参数是在表单域输入的字符串,但如果为表单元素设置enctype=“multipart/form-data”属性,则提交表单时候不再是以字符串方式提交请求参数,而是以二进制编码的方式提交请求,此时直接通过HttpServletRequest的getParameter方法就无法正常获取请求参数的值,而通过二进制流来获取请求内容,就可以获取到上传文件的内容,从而实现文件上传的功能。
Struts2的文件上传支持在原有的文件上传项目上做了进一步的封装,只需要将属性封装表单的文件域,就可非常轻松地完成文件上传。
一、首先讲解一下,在页面中标签form表单中的属性:
1)action属性指定了表中提交的URL;
2)method属性指定是以POST方式还是GET方式提交请求;
3) Enctype属性指的是表单数据的编码方式,该属性有如下3个值:
application/x-www-form-urlencoded:默认编码方式,它只处理表单 里的value属性值。
multipart/form-data:指的是以二进制流的凡是来处理表单数据,这 种方式会把文件或者文件的内容也封装到请求参数里。
text/plain:当表单的action属性为mailto:url的形式时比较方便, 这种方式主要适用于直接通过表单发送邮件的方式。
二、使用Struts2完成文件上传
1.前端页面必须满足条件
1) 必须同步提交 form 表单
2) Form 表单编码方式 multipart/form-data
3) 提交方式必须为 post
4) 上传文件对应 标签input type=”file” 元素要提供 name 属性
演示代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Struts完成文件上传</title> </head> <body> <!-- 为了完成文件上传: 1)标签form表单设置enctype=“multipart/form-data”属性; 2)表单为同步提交方式 method="post"; 3)上传文件对应 标签input type=”file” 元素要提供 name 属性 --> <form action="${pageContext.request.contextPath}/fileUpload" enctype="multipart/form-data" method="post"> 文件标题:<input type="text" name="title" /><br /> 选择文件:<input type="file" name="uploadObj" /><br /> <input type="submit" value="上传" /> </form> </body> </html>
2.服务器端Action注意事项
1)提供文件上传的三个属性
private File xxx 该属性封装了该文件域对应的文件内容;
private xxxFileName 该属性封装了该文件与对应的文件的文件名;
private xxxContentType 该属性封装了该文件与对应的文件的文件类型;
UploadAction中代码演示:
package cn.struts2.action.upload; import java.io.File; import org.apache.commons.io.FileUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.ValueStack; //继承ActionSupport为了接受页面其他参数; public class FileUploadAction extends ActionSupport { private File uploadObj; // 上传文件对象 private String uploadObjFileName; // 上传文件名称 private String uploadObjContentType;// 上传文件类型 private String title; // 页面表单中参数 public File getUploadObj() { return uploadObj; } public void setUploadObj(File uploadObj) { this.uploadObj = uploadObj; } public String getUploadObjFileName() { return uploadObjFileName; } public void setUploadObjFileName(String uploadObjFileName) { this.uploadObjFileName = uploadObjFileName; } public String getUploadObjContentType() { return uploadObjContentType; } public void setUploadObjContentType(String uploadObjContentType) { this.uploadObjContentType = uploadObjContentType; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } // 完成文件上传的方法 public String uploadFile() { try { // 获取服务器端upload文件夹目录的绝对磁盘路径 String path = ServletActionContext.getServletContext().getRealPath("/upload"); // 创建一个服务文件 File file = new File(path,uploadObjFileName); //使用struts2的封装的工具FileUtils,完成文件上传 FileUtils.copyFile(uploadObj, file); //传递文件对象和目标路径 //将文件标题和上传文件路径存入值栈 ValueStack vs = ActionContext.getContext().getValueStack(); vs.set("title", title); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("上传文件失败"); } return SUCCESS; } }
3.在配置Struts.xml文件上传的Action与配置普通Action并没有太大的区别,一样是指定该Action的name,以及该Action的实现类。
当然,还应该为该Action配置<result .../>元素。
代码演示:
<!-- 配置页面请求路径和访问到Action中的方法 --> <package name="default" namespace="/" extends="struts-default"> <action name="fileUpload" class="cn.struts2.action.upload.FileUploadAction" method="uploadFile"> <result name="success" >/success.jsp</result> </action>
4.最后web.xml文件的配置:
1)定义struts2的核心filter
2)定义Struts2核心Filter拦截的URL
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>struts_demo</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <filter> <!-- 定义struts2的核心filter --> <filter-name>struts2Filter</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <!-- 定义Struts2核心Filter拦截的URL--> <filter-mapping> <filter-name>struts2Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
5.完成这些配置后,如果我们在页面点击选择文件,并游览到需要上传的文件,然后单击“上传”按钮,该上传请求将被UploadAction处理,处理结束后转入success.jsp页面,该页面使用了简单的Struts2标签来显示文件上传。
success.jsp页面的代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>上传文件成功</title> </head> <body> <h2>上传文件成功!</h2> <!-- 输出表单中上传文件的标题属性的名称和文件内容 --> 文件标题:<s:property value="title" ></s:property><br> 文件:<img src="<s:property value=‘file‘></s:property>" style="width: 200px;height: 200px"> </body> </html>
通过以上案例,文件大小限制、文件类型处理等问题,我们如何来解决呢?
1)实现文件过滤
在action中设置拦截器;并其设置属性的值,实现相关的功能(可以拦截上传指定类型的文件--否则给用户跳转到提示页面)
或者在配置文件声明常量:
<constant name=”struts.multipart.maxSize” value=”209715200”></contant>
注释说明:
如果在struts.xml文件中,导入自定义的拦截器,那么同时也要将默认的拦截器defaultStack导入。
如果在单数设置某个action的上传文件大小,超过了系统默认大小是不起作用的。