一。关键点说明:
1.页面说明
表单元素的enctype属性
表单的enctype属性指定的是表单数据的编码方式,该属性有如下3个值:
application/x-www-form-urlencoded:这是默认的编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL编码方式。
multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数里。
text/plain:这种编码方式当表单的action属性为mailto:URL的形式时比较方便,这种方式主要适用于直接通过表单发送邮件的方式。
2.配置文件说明
在Struts2的struts.properties配置文件中,有如下配置代码,它们主要用于配置Struts2上传文件时的上传解析器。
#指定使用COS的文件上传解析器
#struts.multipart.parser=cos
#指定使用Pell的文件上传解析器
#struts.multipart.parser=pell
#Struts2默认使用Jakarta的Common-FileUpload的文件上传解析器
struts.multipart.parser=jakarta
使用jakarta解析器需要commons-io-xxx.jar和commons-fileupload-xxx.jar两个jar包支持(已包含在struts2提供的jar包中)
###了解-等搞上传文件时测试
## 指定文件上传的临时目录。默认使用javax.servlet.context.tempdir。
struts.multipart.saveDir=
###了解-等搞上传文件时测试
## 指定允许上传的文件最大字节数。默认值是2097152。
struts.multipart.maxSize=2097152
可以在多个位置控制文件上传大小。但控制分先后顺序。
struts.properties控制---->fileUpload拦截器控制---->action代码控制
例如配置如下则有效,控制越来越精准。
1GB---->512MB---->10MB
例如配置如下则只有properties有效,其他无效。
10MB---->512MB---->1GB
对于JAVA应用而言,比较常用的上传框架有两个:Common-FileUpload和COS。
二。编写测试用例:
开始编写实例:实例中实现了过滤文件类型逻辑,其实可以由内置的fileUpload拦截器控制。
1.编写JSP页面
重点在于将form标签的enctype属性赋值为:multipart/form-data
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
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>文件上传</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>
${ requestScope.typeError }
<!-- 设置表单的enctype属性为multipart/form-data -->
<form id="form1" name="form1" enctype="multipart/form-data" method="post" action="updateFile.action">
文件标题:<input type="text" name="title" value="${requestScope.title }"/><br/>
选择文件:<input type="file" name="upload" value="${requestScope.upload }"/><br/>
<input type="submit" value="提交"><br/>
</form>
</body>
</html>
代码说明:
${ requestScope.typeError }用于输出错误信息。
错误信息来源于Action类中
ActionContext.getContext().put("typeError", "您要上传的文件类型不正确!!!");
所添加的内容。
2.编写Action类
重点在于三个由Struts2提供的属性 xxx、xxxContentType、xxxFileName;xxx由JSP页面的file标签的name属性值控制。
类型为File的xxx属性封装了该文件域对应的文件内容。
类型为String的xxxFileName属性封装了该文件域对应的文件的文件名。
类型为String的xxxContentType属性封装了该文件域对应的文件的文件类型。
package action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilterReader;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileUpdateAction extends ActionSupport{
//封装文件标题请求参数的属性
private String title;
//封装上传文件域的属性
private File upload;
//封装上传文件类型的属性
private String uploadContentType;
//封装上传文件名的属性
private String uploadFileName;
//接受依赖注入的属性-文件保存路径
private String savePath;
//接受依赖注入的属性-允许上传文件类型
private String allowType;
@Override
public String execute() throws Exception {
//判断上传文件类型是否满足要求
String filterResult = filterType(getAllowType().split(","));
//如果当前文件类型不允许上传
if( null != filterResult ) {
ActionContext.getContext().put("typeError", "您要上传的文件类型不正确!!!");
return filterResult;
}
//以服务器的文件保存地址和原文件名建立上传文件输出流
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\" +
getUploadFileName());
//以上传文件建立一个文件上传流
FileInputStream fis = new FileInputStream(getUpload());
//将上传文件的内容写入服务器
byte[] buffer = new byte[1024];
int len = 0 ;
while( (len = fis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
return SUCCESS;
}
public String filterType(String[] types) {
//获取上传文件的文件类型
String fileType = getUploadContentType();
//遍历
for( String type : types ) {
if( type.equals(fileType) ) {
return null;
}
}
return INPUT;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
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 String getSavePath() {
return ServletActionContext.getRequest().getRealPath(savePath);
// return savePath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public String getAllowType() {
return allowType;
}
public void setAllowType(String allowType) {
this.allowType = allowType;
}
}
属性说明:
title:由JSP页面元素传递。
upload:由JSP页面元素传递。
uploadContentType:Struts2提供。
uploadFileName:Struts2提供。
savePath:由struts.xml配置文件中<param name="savePath">/upload</param>设置提供。
allowType:由struts.xml配置文件中<param name="allowType">txt,exe,text/plain</param>设置提供。
方法说明:
filterType方法用于过滤文件类型,当发现非法类型时返回"INPUT"字符串跳转到INPUT指定的物理页面。
代码说明:
fos.close(); 如果不关闭数据流,该文件可能一直被JAVA占领,不可其他软件使用。
ActionContext.getContext().put("typeError", "您要上传的文件类型不正确!!!");将错误信息写到栈中。
与普通的action配置无区别
<action name="updateFile" class="action.FileUpdateAction">
<!-- 动态配置文件保存路径 -->
<param name="savePath">/upload</param>
<!-- 动态配置允许上传文件类型,英文逗号分割 -->
<param name="allowType">txt,exe,text/plain</param>
<result name="success">/FileSuccess.jsp</result>
<result name="input">/FileUpdate4.jsp</result>
</action>
三。关于文件上传的拦截器fileUpload介绍
fileUpload拦截器的定义<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
fileUpload拦截器的参数
allowedTypes:该参数指定允许上传的文件类型,多个文件类型之间以英文逗号分割(,)。
maximumSize:该参数指定允许上传的文件大小,单位是字节。
fileUpload拦截器的配置
<action name="updateFile" class="action.FileUpdateAction">
<!-- 配置fileUpload的拦截器 -->
<interceptor-ref name="fileUpload">
<!-- 配置允许上传的文件类型 -->
<param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg</param>
<!-- 配置允许上传的文件大小 -->
<param name="maximumSize">2000</param>
</interceptor-ref>
<!-- 动态配置文件保存路径 -->
<param name="savePath">/upload</param>
<!-- 动态配置允许上传文件类型,英文逗号分割 -->
<param name="allowType">txt,exe,text/plain</param>
<result name="success">/FileSuccess.jsp</result>
<result name="input">/FileUpdate4.jsp</result>
</action>
被拦截器拦截后抛出错误信息显示到JSP页面中默认为英文,在国际化配置文件中修改如下配置进行国际化配置。
struts.messages.error.file.too.large:当上传文件大小不满足要求时提示信息。
struts.messages.error.file.not.allowed:当上传文件类型不满足要求时提示信息。
struts.messages.error.uploading:当上传文件引发未知的错误时提示信息。
四。同时上传多个文件
与上传一个文件同理,不同点在于
JSP页面中多个上传标签的name名称相同。
struts.xml配置中不变。
Action中用数组或集合接受file属性,String2提供的另外两个属性也使用数组或集合接受。
使用循环分别处理每个file文件
五。Struts2的文件下载实例编码
1.JSP页面编写
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
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>文件下载</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>
<!-- 设置表单的enctype属性为multipart/form-data multipart/form-data -->
<form id="form1" name="form1" method="post" action="downFile.action">
<input type="submit" value="提交"><br/>
</form>
<a href="downFile.action">下载文件</a>
</body>
</html>
2.struts.xml文件编写
重点:
result的type属性为stream。
contentType:指定下载文件的文件类型。
下载文件为固定类型时,与互联网MIME标准中的规定类型一致。
例如text/plain代表纯文本,text/xml表示XML,image/gif代表GIF图片,image/jpeg代表JPG图片。
下载文件为动态内容时,设置为“application/octet-stream;charset=ISO8859-1 ”;
inputName:指定下载文件数据流的来源(action类中方法名)。
contentDisposition:指定文件下载名称与文件下载的处理方式,包括内联(inline)和附件(attachment)两种方式,附件方式会弹出文件保存对话框,否则浏览器会尝试直接显示文件。取值为:attachment;filename="struts2.txt" ,表示文件下载的时候保存的名字应为struts2.txt 。如果直接写filename="struts2.txt" ,那么默认情况是代表inline ,浏览器会尝试自动打开它,等价于这样的写法:inline; filename="struts2.txt"。
bufferSize:指定下载文件的缓冲大小。
<action name="downFile" class="action.FileDownAction">
<!-- 动态配置下载文件路径 -->
<param name="inputPath">\down\1.gif</param>
<!-- 动态配置下载文件名称 -->
<param name="中文文件名称.jpg"</param>
<result name="success" type="stream">
<!-- 指定下载文件的文件类型 -->
<param name="contentType">image/gif</param>
<!-- 指定下载文件的文件位置 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
<!-- 指定下载文件的缓冲大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
配置说明:
<param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
调用Action类中getDownloadFileName()方法,使用返回值做文件名称。该方法有效解决中文名称乱码问题。
3.action代码编写
重点:getTargetFile()方法与struts.xml配置文件中inputName配置对应。
package action;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* 文件下载Action
*/
public class FileDownAction extends ActionSupport{
//该属性是依赖注入的属性-可以在配置文件中动态指定该属性
private String fileName;//下载文件名称(也可以作为参数从页面传递进来)
//该属性是依赖注入的属性-可以在配置文件中动态指定该属性值
private String inputPath;//下载文件路径(也可以作为参数从页面传递进来)
/**
* 下载用的Action应该返回一个InputStream实例
* 该方法对应在result里的inputName属性值为targetFile
*/
public InputStream getTargetFile() throws Exception{
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
/** 提供转换编码后的供下载用的文件名 */
public String getDownloadFileName() {
String downFileName = fileName;
try {
downFileName = new String(downFileName.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return downFileName;
}
public String execute() throws Exception {
return SUCCESS;
}
public String getInputPath() {
return inputPath;
}
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
代码说明:
inputPate:数据来源于struts.xml配置文件中<param name="inputPath">\down\1.gif</param>。
fileName;数据来源于struts.xml配置文件中<param name="中文文件名称.jpg"</param>。
四。MIME标准
'ez' => 'application/andrew-inset',
'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
'doc' => 'application/msword',
'bin' => 'application/octet-stream',
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'class' => 'application/octet-stream',
'so' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => 'application/pdf',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'wbxml' => 'application/vnd.wap.wbxml',
'wmlc' => 'application/vnd.wap.wmlc',
'wmlsc' => 'application/vnd.wap.wmlscriptc',
'bcpio' => 'application/x-bcpio',
'vcd' => 'application/x-cdlink',
'pgn' => 'application/x-chess-pgn',
'cpio' => 'application/x-cpio',
'csh' => 'application/x-csh',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'spl' => 'application/x-futuresplash',
'gtar' => 'application/x-gtar',
'hdf' => 'application/x-hdf',
'js' => 'application/x-javas
cript',
'skp' => 'application/x-koan',
'skd' => 'application/x-koan',
'skt' => 'application/x-koan',
'skm' => 'application/x-koan',
'latex' => 'application/x-latex',
'nc' => 'application/x-netcdf',
'cdf' => 'application/x-netcdf',
'sh' => 'application/x-sh',
'shar' => 'application/x-shar',
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'sv4cpio' => 'application/x-sv4cpio',
'sv4crc' => 'application/x-sv4crc',
'tar' => 'application/x-tar',
'tcl' => 'application/x-tcl',
'tex' => 'application/x-tex',
'texinfo' => 'application/x-texinfo',
'texi' => 'application/x-texinfo',
't' => 'application/x-troff',
'tr' => 'application/x-troff',
'roff' => 'application/x-troff',
'man' => 'application/x-troff-man',
'me' => 'application/x-troff-me',
'ms' => 'application/x-troff-ms',
'ustar' => 'application/x-ustar',
'src' => 'application/x-wais-source',
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'zip' => 'application/zip',
'au' => 'audio/basic',
'snd' => 'audio/basic',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'kar' => 'audio/midi',
'mpga' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'aif' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'm3u' => 'audio/x-mpegurl',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'wav' => 'audio/x-wav',
'pdb' => 'chemical/x-pdb',
'xyz' => 'chemical/x-xyz',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'ief' => 'image/ief',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'png' => 'image/png',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'djvu' => 'image/vnd.djvu',
'djv' => 'image/vnd.djvu',
'wbmp' => 'image/vnd.wap.wbmp',
'ras' => 'image/x-cmu-raster',
'pnm' => 'image/x-portable-anymap',
'pbm' => 'image/x-portable-bitmap',
'pgm' => 'image/x-portable-graymap',
'ppm' => 'image/x-portable-pixmap',
'rgb' => 'image/x-rgb',
'xbm' => 'image/x-xbitmap',
'xpm' => 'image/x-xpixmap',
'xwd' => 'image/x-xwindowdump',
'igs' => 'model/iges',
'iges' => 'model/iges',
'msh' => 'model/mesh',
'mesh' => 'model/mesh',
'silo' => 'model/mesh',
'wrl' => 'model/vrml',
'vrml' => 'model/vrml',
'css' => 'text/css',
'html' => 'text/html',
'htm' => 'text/html',
'asc' => 'text/plain',
'txt' => 'text/plain',
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'sgml' => 'text/sgml',
'sgm' => 'text/sgml',
'tsv' => 'text/tab-separated-values',
'wml' => 'text/vnd.wap.wml',
'wmls' => 'text/vnd.wap.wmlscript',
'etx' => 'text/x-setext',
'xsl' => 'text/xml',
'xml' => 'text/xml',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'mxu' => 'video/vnd.mpegurl',
'avi' => 'video/x-msvideo',
'movie' => 'video/x-sgi-movie',
'ice' => 'x-conference/x-cooltalk'