Struts2-文件上传下载-解决下载中文乱码问题

一。关键点说明:

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", "您要上传的文件类型不正确!!!");将错误信息写到栈中。



3.配置struts.xml文件

与普通的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'
































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值