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代码为:
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>
在这里要注意的是要引入标签:
- <%@ taglib uri="/struts-tags" prefix="s"%>
上面的页面只是一个普通的html页面,没有任何的动态部分,当该页面提交请求的时候发送到/csdn/uploadList.action,这是一个struts2的action。
Struts2的Action无需负责处理HttpServletRequest请求,因为struts2的Action已经与servletAPI彻底分离了,struts2框架负责解析httpServletRequest请求的参数,包括文件域,strtus2使用File类型来封装文件域。
3.下面是处理Action的代码:
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
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中用拦截器来设置
显示的错误提示信息的标签为:
<s:fielderror></s:fielderror>
以上的多个文件上传是List集合的,数组的也不过如此,要改变的地方为Action接收的时候类型的不同和读取的时候循环不同,下面的数组的例子为: