http://blog.csdn.net/aaa1aaaaa/article/details/7533629
多个文件上传分为List集合和数组,下面我们着重介绍一下list集合的上传。都大同小异。
一 介绍
1. 在struts2文件上传的时候要先导入struts2的几个包,在struts2.3.1.2中,导入的包如图所视:
从图上可以看出其中文件上传所需要的是包为commons-fileupload-1.2.2.jar和commons-io-2.0.1.jar包。
2. Struts2文件上传并未提供自己的请求解析器,也就是说,struts2不会自己去处理multipart/form-data的请求,它需要调用其他的请求解析器,将http请求中的表单域解析出来。但struts2在原有的上传解析器继承上做了进一步封装,更进一步简化了文件上传。
3. Struts2默认使用的是Jakarta和Connon-FileUpload的文件上传框架,因此,如果需要使用struts2的文件上传功能,则需要在Web应用导入上面我所说的几个包
4. Struts2的文件上传支持在原有的问上传项目上做了进一步封装,简化了文件上传代码实现,取消了不同上传项目上编程差异。
二 实例
1. 首先我们来了解一下表单属性enctype属性的意义
表单的enctype属性指定的是表单数据的编码方式,该属性呢有3个值
(1) application/x-www-form-urlencoded,这是默认的编码方式,它只能处理表单域里的value属性,采用这种编码方式的表单会将表单域的值处理成URL编码方式。
(2) multipart/form-data,采用这种编码方式会以二进制流的方式来处理表单数据 ,这种编码方式会把文件域指定文件的内容也封装到请求参数里。
(3) text/plain,这种编码方式当表单的action属性为mailto:URL的形式是比较方便,这种方式主要适用于直接通过表单发送邮件的方式。
从以上的介绍可以看出为什么文件上传要用到的是multipart/form-data属性了吧!上传的文件会在底层封装,并通过二进制流读取。
2. 下面我们来写这样一个界面来实现多文件的上传:效果如下图:
所用的html代码为:
- <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
- <%@ taglib uri="/struts-tags" prefix="s"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>My JSP 'tagUpload.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css">
- -->
- </head>
- <body>
- <h3>多个文件上传实例</h3>
- <s:form action="/csdn/uploadList.action" enctype="multipart/form-data" method="post">
- <s:textfield label="上传名称" name="name"></s:textfield>
- <s:file label="上传文件" name="upload"></s:file>
- <s:file label="上传文件" name="upload"></s:file>
- <s:file label="上传文件" name="upload"></s:file>
- <s:submit value="上传" />
- </s:form>
- </body>
- </html>
在这里要注意的是要引入标签:
- <%@ taglib uri="/struts-tags" prefix="s"%>
上面的页面只是一个普通的html页面,没有任何的动态部分,当该页面提交请求的时候发送到/csdn/uploadList.action,这是一个struts2的action。
Struts2的Action无需负责处理HttpServletRequest请求,因为struts2的Action已经与servletAPI彻底分离了,struts2框架负责解析httpServletRequest请求的参数,包括文件域,strtus2使用File类型来封装文件域。
3.下面是处理Action的代码:
- package cn.csdn.hr.up.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 com.opensymphony.xwork2.ActionSupport;
- public class TagUploadListAction extends ActionSupport {
- private static final long serialVersionUID = 1L;
- private String name;
- // 上传多个文件的集合文本
- private List<File> upload;
- // /多个上传文件的类型集合
- private List<String> uploadContextType;
- // 多个上传文件的文件名集合
- private List<String> uploadFileName;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public List<File> getUpload() {
- return upload;
- }
- public void setUpload(List<File> upload) {
- this.upload = upload;
- }
- public List<String> getUploadContextType() {
- return uploadContextType;
- }
- public void setUploadContextType(List<String> uploadContextType) {
- this.uploadContextType = uploadContextType;
- }
- public List<String> getUploadFileName() {
- return uploadFileName;
- }
- public void setUploadFileName(List<String> uploadFileName) {
- this.uploadFileName = uploadFileName;
- }
- public String execute() {
- // 把上传的文件放到指定的路径下
- String path = ServletActionContext.getServletContext().getRealPath(
- "/WEB-INF/uploadList");
- // 写到指定的路径中
- File file = new File(path);
- // 如果指定的路径没有就创建
- if (!file.exists()) {
- file.mkdirs();
- }
- // 把得到的文件的集合通过循环的方式读取并放在指定的路径下
- for (int i = 0; i < upload.size(); i++) {
- try {
- //list集合通过get(i)的方式来获取索引
- FileUtils.copyFile(upload.get(i), new File(file, uploadFileName.get(i)));
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return SUCCESS;
- }
- }
通过以上的Action我们可以看出Action还包括了两个属性,uploadFileName,uploadContextType, 这两个属性分别用来封装上传我文件的文件名,上传文件的文件类型,这两个属性体现了struts设计的灵巧、简化之处,Action类直接通过File类型属性直接封装了上传文件的内容,但这个File属性无法获取上传文件的文件名和文件类型,所以struts2直接将包含的上传文件名和文件类型的信息封装到uploadFileName,uploadContextType属性中,可以认为:如果表单中包含一个name属性为xxx的文件域,则对应的Action需要使用3个属性来封装该文件域的信息:
(1) 类型为File的xxx属性封装了该文件域对应的文件内容
(2) 类型为String的xxxFileName属性封装了该案文件域对应的文件的文件类型
(3) 类型为String的xxxContextType属性封装了该文件域对应的文件的类型
通过上吗的三个属性可以简单的实现上传文件的文件名、文件类型和文件内容
3. 配置action的strtus.xml
- <?xml version="1.0" encoding="GBK"?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
- <struts>
- <package name="file" extends="struts-default" namespace="/csdn">
- <action name="uploadList" class="cn.csdn.hr.up.action.TagUploadListAction">
- <result>../success.jsp</result>
- <result name="input">../tagUpload.jsp</result>
- </action>
- </package>
- </struts>
4. 设置上传的文件的大小和类型
就是在struts.xml中用拦截器来设置
- <action name="uploadList" class="cn.csdn.hr.up.action.TagUploadListAction">
- <result>../success.jsp</result>
- <result name="input">../tagUpload.jsp</result>
- <!-- 通过拦截器来限制上传图片的类型和大小 -->
- <interceptor-ref name="fileUpload">
- <param name="allowedTypes">image/bmp,image/x-png,image/gif</param>
- <param name="maximumSize">200</param>
- </interceptor-ref>
- <interceptor-ref name="defaultStack"></interceptor-ref>
- </action>
显示的错误提示信息的标签为:
<s:fielderror></s:fielderror>
以上的多个文件上传是List集合的,数组的也不过如此,要改变的地方为Action接收的时候类型的不同和读取的时候循环不同,下面的数组的例子为:
- // 得到上传文件的名称一定与name值一直
- private File upload[];
- // 上传文件的类型 ContentType
- private String uploadContentType[];
- // 上传文件的名称
- private String uploadFileName[];
- public File[] getUpload() {
- return upload;
- }
- public void setUpload(File[] upload) {
- this.upload = upload;
- }
- public String[] getUploadContentType() {
- return uploadContentType;
- }
- public void setUploadContentType(String[] uploadContentType) {
- this.uploadContentType = uploadContentType;
- }
- public String[] getUploadFileName() {
- return uploadFileName;
- }
- public void setUploadFileName(String[] uploadFileName) {
- this.uploadFileName = uploadFileName;
- }
- public static long getSerialversionuid() {
- return serialVersionUID;
- }
- public String uploads() {
- String path = ServletActionContext.getServletContext().getRealPath(
- "/upload");
- // 写到指定路径
- File file = new File(path);
- //判断指定的路径下是否有uplaod,如果没有,自动创建
- if (!file.exists()) {
- file.mkdirs();
- }
- try {
- for(int i = 0;i<upload.length;i++){
- FileUtils.copyFile(upload[i], new File(file, uploadFileName[i]));
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return SUCCESS;
- }
.a : |
application/octet-stream |
.ai : |
application/postscript |
'.aif' : |
'audio/x-aiff', |
'.aifc' : |
'audio/x-aiff', |
'.aiff' : |
'audio/x-aiff', |
'.au' : ' |
audio/basic', |
'.avi' : |
'video/x-msvideo', |
'.bat' : |
'text/plain', |
'.bcpio' : |
'application/x-bcpio', |
'.bin' : |
'application/octet-stream', |
'.bmp' : |
'image/x-ms-bmp', |
'.c' : |
'text/plain', |
# Duplicates :(
'.cdf' : |
'application/x-cdf', |
'.cdf' |
: 'application/x-netcdf', |
'.cpio' : |
'application/x-cpio', |
'.csh' : |
'application/x-csh', |
'.css' : |
'text/css', |
'.dll' : |
'application/octet-stream', |
'.doc' : |
'application/msword', |
'.dot' : |
'application/msword', |
'.dvi' : |
'application/x-dvi', |
'.eml' : |
'message/rfc822', |
'.eps' : |
'application/postscript', |
'.etx' : |
'text/x-setext', |
'.exe' : |
'application/octet-stream', |
'.gif' : |
'image/gif', |
'.gtar' : |
'application/x-gtar', |
'.h' : |
'text/plain', |
'.hdf' : |
'application/x-hdf', |
'.htm' : |
'text/html', |
'.html' : |
'text/html', |
'.ief' : |
'image/ief', |
'.jpe' : |
'image/jpeg', |
'.jpeg' : |
'image/jpeg', |
'.jpg' : |
'image/jpeg', |
'.js' : |
'application/x-javascript', |
'.ksh' : |
'text/plain', |
'.latex' : |
'application/x-latex', |
'.m1v' : |
'video/mpeg', |
'.man' : |
'application/x-troff-man', |
'.me' : |
'application/x-troff-me', |
'.mht' : |
'message/rfc822', |
'.mhtml' : |
'message/rfc822', |
'.mif' : |
'application/x-mif', |
'.mov' : |
'video/quicktime', |
'.movie' : |
'video/x-sgi-movie', |
'.mp2' : |
'audio/mpeg', |
'.mp3' : |
'audio/mpeg', |
'.mpa' : |
'video/mpeg', |
'.mpe' : |
'video/mpeg', |
'.mpeg' : |
'video/mpeg', |
'.mpg' : |
'video/mpeg', |
'.ms' : |
'application/x-troff-ms', |
'.nc' : |
'application/x-netcdf', |
'.nws' : |
'message/rfc822', |
'.o' : |
'application/octet-stream', |
'.obj' : |
'application/octet-stream', |
'.oda' : |
'application/oda', |
'.p12' : |
'application/x-pkcs12', |
'.p7c' : |
'application/pkcs7-mime', |
'.pbm' : |
'image/x-portable-bitmap', |
'.pdf' : |
'application/pdf', |
'.pfx' : |
'application/x-pkcs12', |
'.pgm' : |
'image/x-portable-graymap', |
'.pl' : |
'text/plain', |
'.png' : |
'image/png', |
'.pnm' : |
'image/x-portable-anymap', |
'.pot' : |
'application/vnd.ms-powerpoint', |
'.ppa' : |
'application/vnd.ms-powerpoint', |
'.ppm' : |
'image/x-portable-pixmap', |
'.pps' : |
'application/vnd.ms-powerpoint', |
'.ppt' : |
'application/vnd.ms-powerpoint', |
'.ps' : |
'application/postscript', |
'.pwz' : |
'application/vnd.ms-powerpoint', |
'.py' : |
'text/x-python', |
'.pyc' : |
'application/x-python-code', |
'.pyo' : |
'application/x-python-code', |
'.qt' : |
'video/quicktime', |
'.ra' : |
'audio/x-pn-realaudio', |
'.ram' : |
'application/x-pn-realaudio', |
'.ras' : |
'image/x-cmu-raster', |
'.rdf' : |
'application/xml', |
'.rgb' : |
'image/x-rgb', |
'.roff' : |
'application/x-troff', |
'.rtx' : |
'text/richtext', |
'.sgm' : |
'text/x-sgml', |
'.sgml' : |
'text/x-sgml', |
'.sh' : |
'application/x-sh', |
'.shar' : |
'application/x-shar', |
'.snd' : |
'audio/basic', |
'.so' : |
'application/octet-stream', |
'.src' : |
'application/x-wais-source', |
'.sv4cpio': |
'application/x-sv4cpio', |
'.sv4crc' : |
'application/x-sv4crc', |
'.swf' : |
'application/x-shockwave-flash', |
'.t' : |
'application/x-troff', |
'.tar' : |
'application/x-tar', |
'.tcl' : |
'application/x-tcl', |
'.tex' : |
'application/x-tex', |
'.texi' : |
'application/x-texinfo', |
'.texinfo': |
'application/x-texinfo', |
'.tif' : |
'image/tiff', |
'.tiff' : |
'image/tiff', |
'.tr' : |
'application/x-troff', |
'.tsv' : |
'text/tab-separated-values', |
'.txt' : |
'text/plain', |
'.ustar' : |
'application/x-ustar', |
'.vcf' : |
'text/x-vcard', |
'.wav' : |
'audio/x-wav', |
'.wiz' : |
'application/msword', |
'.wsdl' : |
'application/xml', |
'.xbm' : |
'image/x-xbitmap', |
'.xlb' : |
'application/vnd.ms-excel', |
# Duplicates :(
'.xls' : |
'application/excel', |
'.xls' : |
'application/vnd.ms-excel', |
.xml : |
text/xml |
.xpdl: |
application/xml |
.xpm : |
image/x-xpixmap |
.xsl : |
application/xml |
.xwd : |
image/x-xwindowdump |
.zip : |
application/zip |
firefox 和 ie 的文件类型区别
Firefox: |
image/jpeg, image/bmp, image/gif, image/png |
ie 6: |
image/pjpeg ,image/bmp, image/gif, image/x-png |
ie 7: |
image/pjpeg, image/bmp, image/gif, image/x-png |
ie 8: |
image/pjpeg, image/bmp, image/gif, image/x-png |
Ie 9: |
image/jpeg, image/bmp, image/gif, image/png |
所以在struts.xml配置文件中需要
<param name="allowedTypes">
image/bmp,image/png,image/gif,image/jpeg,image/jpg,
image/pjpeg ,image/bmp, image/gif, image/x-png,
</param>