Struts2多个文件上传的分析及源代码说明

Struts2多个文件上传

10级学员 韩晓爽课堂笔记

多个文件上传分为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代码为:

[html] view plaincopy
 
 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
 2   
 3 <%@ taglib uri="/struts-tags" prefix="s"%>  
 4   
 5 <%  
 6     String path = request.getContextPath();  
 7   
 8     String basePath = request.getScheme() + "://"  
 9   
10            + request.getServerName() + ":" + request.getServerPort()  
11   
12            + path + "/";  
13 %>  
14   
15 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
16   
17 <html>  
18   
19     <head>  
20   
21        <base href="<%=basePath%>">  
22   
23        <title>My JSP 'tagUpload.jsp' starting page</title>  
24   
25        <meta http-equiv="pragma" content="no-cache">  
26   
27        <meta http-equiv="cache-control" content="no-cache">  
28   
29        <meta http-equiv="expires" content="0">  
30   
31        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
32   
33        <meta http-equiv="description" content="This is my page">  
34   
35        <!-- 
36  
37     <link rel="stylesheet" type="text/css" href="styles.css"> 
38  
39     -->  
40     </head>  
41     <body>  
42       <h3>多个文件上传实例</h3>  
43        <s:form action="/csdn/uploadList.action" enctype="multipart/form-data" method="post">  
44            <s:textfield label="上传名称" name="name"></s:textfield>  
45            <s:file label="上传文件" name="upload"></s:file>  
46            <s:file label="上传文件" name="upload"></s:file>  
47            <s:file label="上传文件" name="upload"></s:file>  
48            <s:submit value="上传" />  
49        </s:form>  
50     </body>  
51 </html>   

 

 

在这里要注意的是要引入标签:

[html] view plaincopy
 
  1. <%@ taglib uri="/struts-tags" prefix="s"%>  

       上面的页面只是一个普通的html页面,没有任何的动态部分,当该页面提交请求的时候发送到/csdn/uploadList.action,这是一个struts2的action。

    Struts2的Action无需负责处理HttpServletRequest请求,因为struts2的Action已经与servletAPI彻底分离了,struts2框架负责解析httpServletRequest请求的参数,包括文件域,strtus2使用File类型来封装文件域。

3.下面是处理Action的代码:

[java] view plaincopy
 
 1 package cn.csdn.hr.up.action;  
 2 import java.io.File;  
 3 import java.io.IOException;  
 4 import java.util.List;  
 5 import org.apache.commons.io.FileUtils;  
 6 import org.apache.struts2.ServletActionContext;  
 7 import com.opensymphony.xwork2.ActionSupport;  
 8 public class TagUploadListAction extends ActionSupport {  
 9     private static final long serialVersionUID = 1L;  
10     private String name;  
11   
12     // 上传多个文件的集合文本  
13   
14     private List<File> upload;  
15     // /多个上传文件的类型集合  
16     private List<String> uploadContextType;  
17    // 多个上传文件的文件名集合  
18     private List<String> uploadFileName;  
19   
20     public String getName() {  
21             return name;  
22      }  
23   
24     public void setName(String name) {  
25   
26        this.name = name;  
27     }  
28   
29     public List<File> getUpload() {  
30   
31        return upload;  
32     }  
33   
34     public void setUpload(List<File> upload) {  
35   
36        this.upload = upload;  
37     }  
38   
39     public List<String> getUploadContextType() {  
40   
41        return uploadContextType;  
42     }  
43   
44     public void setUploadContextType(List<String> uploadContextType) {  
45   
46        this.uploadContextType = uploadContextType;  
47     }  
48   
49     public List<String> getUploadFileName() {  
50   
51        return uploadFileName;  
52     }  
53   
54     public void setUploadFileName(List<String> uploadFileName) {  
55   
56        this.uploadFileName = uploadFileName;  
57     }  
58   
59     public String execute() {  
60   
61        // 把上传的文件放到指定的路径下  
62   
63        String path = ServletActionContext.getServletContext().getRealPath(  
64   
65               "/WEB-INF/uploadList");  
66   
67        // 写到指定的路径中  
68   
69        File file = new File(path);  
70   
71        // 如果指定的路径没有就创建  
72   
73        if (!file.exists()) {  
74   
75            file.mkdirs();  
76        }  
77   
78        // 把得到的文件的集合通过循环的方式读取并放在指定的路径下  
79   
80        for (int i = 0; i < upload.size(); i++) {  
81            try {  
82   
83               //list集合通过get(i)的方式来获取索引  
84   
85               FileUtils.copyFile(upload.get(i), new File(file, uploadFileName.get(i)));  
86   
87            } catch (IOException e) {  
88   
89               // TODO Auto-generated catch block  
90   
91               e.printStackTrace();  
92            }  
93        }  
94   
95        return SUCCESS;  
96     }  
97 }  

 

通过以上的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

[html] view plaincopy
 
 1 <?xml version="1.0" encoding="GBK"?>  
 2   
 3 <!DOCTYPE struts PUBLIC  
 4   
 5     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"  
 6   
 7     "http://struts.apache.org/dtds/struts-2.3.dtd">  
 8   
 9 <struts>  
10     <package name="file" extends="struts-default" namespace="/csdn">  
11   
12        <action name="uploadList" class="cn.csdn.hr.up.action.TagUploadListAction">  
13   
14            <result>../success.jsp</result>  
15   
16            <result name="input">../tagUpload.jsp</result>  
17   
18        </action>  
19     </package>  
20 </struts>  

 

4. 设置上传的文件的大小和类型

就是在struts.xml中用拦截器来设置   

[html] view plaincopy
 

 

 1 <action name="uploadList" class="cn.csdn.hr.up.action.TagUploadListAction">  
 2   
 3            <result>../success.jsp</result>  
 4   
 5            <result name="input">../tagUpload.jsp</result>  
 6   
 7            <!-- 通过拦截器来限制上传图片的类型和大小 -->  
 8   
 9            <interceptor-ref name="fileUpload">  
10   
11               <param name="allowedTypes">image/bmp,image/x-png,image/gif</param>  
12   
13               <param name="maximumSize">200</param>  
14   
15            </interceptor-ref>  
16   
17            <interceptor-ref name="defaultStack"></interceptor-ref>  
18   
19        </action>  

 

 

显示的错误提示信息的标签为:

             <s:fielderror></s:fielderror>

以上的多个文件上传是List集合的,数组的也不过如此,要改变的地方为Action接收的时候类型的不同和读取的时候循环不同,下面的数组的例子为:

[java] view plaincopy
 
 1          // 得到上传文件的名称一定与name值一直
 2     private File upload[];
 3     // 上传文件的类型 ContentType
 4     private String uploadContentType[];
 5     // 上传文件的名称
 6     private String uploadFileName[];
 7     public File[] getUpload() {
 8         return upload;
 9     }
10 
11     public void setUpload(File[] upload) {
12         this.upload = upload;
13     }
14 
15     public String[] getUploadContentType() {
16         return uploadContentType;
17     }
18 
19     public void setUploadContentType(String[] uploadContentType) {
20         this.uploadContentType = uploadContentType;
21     }
22 
23     public String[] getUploadFileName() {
24         return uploadFileName;
25     }
26 
27     public void setUploadFileName(String[] uploadFileName) {
28         this.uploadFileName = uploadFileName;
29     }
30 
31     public static long getSerialversionuid() {
32         return serialVersionUID;
33     }
34 
35     public String uploads() {
36         String path = ServletActionContext.getServletContext().getRealPath(
37                 "/upload");
38 
39         // 写到指定路径
40         File file = new File(path);
41         //判断指定的路径下是否有uplaod,如果没有,自动创建
42         if (!file.exists()) {
43             file.mkdirs();
44         }
45         try {
46             for(int i = 0;i<upload.length;i++){
47                 FileUtils.copyFile(upload[i], new File(file, uploadFileName[i]));
48             }
49         } catch (IOException e) {
50             // TODO Auto-generated catch block
51             e.printStackTrace();
52         }
53         return SUCCESS;
54     }

 

posted @ 2013-10-30 21:43  晴心  阅读(273)  评论(0)    收藏  举报