struts2文件的上传与下载--超出指定文件大小的校验提示

在做B/S架构项目时,经常会遇到文件上传与下载的需求,在struts2框架中帮我们实现的文件上传与下载机制,能够很好地实现项目需求。在使用的时候,需要导入文件上传与下载需要的两个jar,一个是commons-fileupload-x.x.x.jar,另一个是commons-io-x.x.x.jar.

一、文件上传的表单(多文件上传)

在做文件上传时,表单中的method方法必须是post,里边的enctype必须是multipart/form-data。不然会出现莫名其妙的异常。多文件上传的表单通过js技术来做控制。整个上传文件的页面是:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>

<script type="text/javascript" language="JavaScript"
	src="${pageContext.request.contextPath }/script/calendar.js"
	charset="gb2312"></script>
<script language="javascript">
	function checkf() {
		var files = document.getElementsByName("file");
		if (files[0].value.length != 0) {
			return true;
		} else {
			alert("请选择文件");
			return false;
		}
	}
	//添加一行
	function addMore() {
		var td = document.getElementById("more");
		//换行
		var br = document.createElement("br");
		var input = document.createElement("input");
		var button = document.createElement("input");
		input.type = "file";
		input.name = "file";
		button.type = "button";
		button.value = "Remove";
		button.onclick = function() {
			td.removeChild(br);
			td.removeChild(input);
			td.removeChild(button);
		}
		td.appendChild(br);
		td.appendChild(input);
		td.appendChild(button);
	}
</script>

<html>
<head>
<title>测试文件上传的jsp</title>
<link href="${pageContext.request.contextPath }/css/Style.css"
	type="text/css" rel="stylesheet">
</head>

<body>

	<s:form action="upLoadAction_upload.do" method="post" theme="simple"
		enctype="multipart/form-data">
		<table align="center" width="50%" border="1">
			<tr>
				<td>选择上传文件</td>
				<td id="more"><s:file name="file"></s:file> <input
					type="button" value="Add More.." οnclick="addMore()"></td>
			</tr>
			<tr>
				<td><s:submit type="button" value="submit"
						οnclick="return checkf()" /></td>
				<td><s:reset value="reset "></s:reset></td>
			</tr>
		</table>
	</s:form>
</body>
</html>

二、文件上传的Action

在文件上传的action中必须要有三个参数,分别是File类型的file-上传的文件;String类型的fileFileName-上传文件的名称;String类型的fileContentType-文件类型。如果是多文件上传,使用List集合去包裹,也就是List<File> file-上传文件集合;List<Sting> fileFileName-文件名称集合;List<String> fileContentType-文件类型集合。

package cn.ysu.zhy.devmanager.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.struts2.ServletActionContext;
import org.springframework.stereotype.Controller;

@Controller("upLoadAction")
public class UpLoadAction extends BaseAction {
	/**
	 * 1.做文件上传必须得三个参数:file,fileFileName,fileContentType
	 */
	/**
	 * 对应jsp的file标签,表示上传的文件(多文件用集合表示)
	 */
	private List<File> file;
	/**
	 * 文件名称
	 */
	private List<String> fileFileName;

	/**
	 * 文件的类型
	 */
	private List<String> fileContentType;
	/**
	 * 2.下载的文件名
	 */
	private String fileName;
	private String fileUploadErrorMessage;

	public List<File> getFile() {
		return file;
	}

	public void setFile(List<File> file) {
		this.file = file;
	}

	public List<String> getFileFileName() {
		return fileFileName;
	}

	public void setFileFileName(List<String> fileFileName) {
		this.fileFileName = fileFileName;
	}

	public List<String> getFileContentType() {
		return fileContentType;
	}

	public void setFileContentType(List<String> fileContentType) {
		this.fileContentType = fileContentType;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	/**
	 * @Name: home
	 * @Description: 跳转到上传首页upload.jsp
	 * @Author: ZHY(作者)
	 * @Version: V1.00 (版本号)
	 * @Create Date: 2016-10-07 (创建日期)
	 * @Parameters: 无
	 * @Return: String 跳转到上传首页upload.jsp
	 */
	public String home() {

		return "home";
	}

	/**
	 * @throws Exception
	 * @Name: upload
	 * @Description: 处理文件的上传
	 * @Author: ZHY(作者)
	 * @Version: V1.00 (版本号)
	 * @Create Date: 2016-10-07 (创建日期)
	 * @Parameters: 无
	 * @Return: String 上传成功,重定向到upload.jsp
	 */
	public String upload() throws Exception {
		// 1.获取上传的文件路径
		File filePath = new File(ServletActionContext.getServletContext().getRealPath("myUploadFile"));
		// 2.判断目录是否存在,如果不存在创建文件夹
		if (!filePath.exists()) {
			filePath.mkdir();// 创建目录
		}
		System.out.println(filePath);

		if (file != null && file.size() > 0 && fileFileName != null && fileFileName.size() > 0) {
			for (int i = 0; i < file.size(); i++) {
				// 3.声明文件的输入流,为输入流指定路径
				FileInputStream is = new FileInputStream(file.get(i));
				// 获取上传文件的大小(单位是字节1257114280--是1.17G),做数据狭小的限制,如果大于209715200,也就是200M,return
				// error,提示上传文件大小不能超过200M,2097152--2M
				int length = is.available();// 获取上传文件的字节大小
				// 上传的文件超过200M
				if (length >= 209715200) {

					request.setAttribute("error", "您上传的文件超过200M");

					return "error";
				}

				// 4.获取文件输出流,声明输出流的地址已及名称
				FileOutputStream out = new FileOutputStream(filePath + "\\" + fileFileName.get(i));
				try {
					// 5.流对接
					byte[] buffer = new byte[1024];
					int len = 0;
					while ((len = is.read(buffer)) > 0) {
						// 将buffer里的二进制数,从0开始,每次写len这么长,写入输出流中
						out.write(buffer, 0, len);
					}
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					is.close();
					out.close();
				}

			}
		}

		request.setAttribute("fileName", fileFileName);

		return "upload";
	}

	/**
	 * @Name: upload
	 * @Description: 处理文件的下载
	 * @Author: ZHY(作者)
	 * @Version: V1.00 (版本号)
	 * @Create Date: 2016-10-07 (创建日期)
	 * @Parameters: 无
	 * @Return: String 下载成功,重定向到upload.jsp
	 */
	public String download() {

		return "download";
	}

}

三、文件下载的表单

文件下载相对于文件上传要简单一些,在JSP中唯一需要注意的就是中文乱码问题,解决乱码问题使用URLEncoder和URLDecoder基本上就能解决了。

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>

<script type="text/javascript" language="JavaScript"
	src="${pageContext.request.contextPath }/script/calendar.js"
	charset="gb2312"></script>

<html>
<head>
<title>测试文件下载的jsp</title>
<link href="${pageContext.request.contextPath }/css/Style.css"
	type="text/css" rel="stylesheet">
</head>

<body>

	<table align="center" width="50%" border="1">
		<s:if test="#request.fileName != null && #request.fileName.size() > 0">
			<s:iterator value="#request.fileName" var="name">
				<s:set value="name" id="names" name="names" scope="Request" />
				<%
					//没有进行编码
							String fname = (String) request.getAttribute("names");
							//编码之后的值
							String fnameEncode = java.net.URLEncoder.encode(fname, "UTF-8");
				%>
				<tr>
					<td><%=fname%></td>
					<td><a
						href="<s:url value='downLoadAction_download.do'><s:param name='fileName'><%=fnameEncode%></s:param> </s:url>">下载</a>
					</td>
				</tr>
			</s:iterator>
		</s:if>
	</table>
</body>
</html>

四、文件下载的Action

在文件下载的action中,必须有两个参数,一个是String类型的fileName-文件名称和InputStream类型的fileInput-文件下载的流。

package cn.ysu.zhy.devmanager.action;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

import org.apache.struts2.ServletActionContext;
import org.springframework.stereotype.Controller;

/**
 * 文件下载的action
 * 
 * @author ZHY
 * 
 */
@Controller("downLoadAction")
public class DownLoadAction extends BaseAction {
	/**
	 * 下载文件的名称
	 */
	private String fileName;
	/**
	 * 下载的文件
	 */
	private InputStream fileInput;

	public String getFileName() {

		return fileName;
	}

	public void setFileName(String fileName) {
		try {
			fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		this.fileName = fileName;
	}

	public InputStream getFileInput() {
		try {
			fileName = URLDecoder.decode(fileName, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ServletActionContext.getServletContext().getResourceAsStream("myUploadFile\\" + fileName);
	}

	public void setFileInput(InputStream fileInput) {
		this.fileInput = fileInput;
	}

	/**
	 * 下载时,显示中文名字
	 * 
	 */
	public String getDownloadFileName() {
		String downloadFileName = fileName;
		try {
			// 使用ISO8859-1编码
			downloadFileName = new String(downloadFileName.getBytes(), "ISO8859-1");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return downloadFileName;
	}

	/**
	 * @Name: download
	 * @Description: 处理文件的上传
	 * @Author: ZHY(作者)
	 * @Version: V1.00 (版本号)
	 * @Create Date: 2016-10-07 (创建日期)
	 * @Parameters: 无
	 * @Return: String 上传成功,重定向到upload.jsp
	 */
	public String download() {
		try {
			fileName = URLDecoder.decode(fileName, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		fileInput = ServletActionContext.getServletContext().getResourceAsStream("myUploadFile\\" + fileName);
		if (fileInput == null) {
			return "error";
		}
		return "download";
	}

}
OK了,至此,文件上传与下载的功能就实现了。但是存在一个问题,就是struts2中默认支持能够上传的文件大小是2M,在项目开发过程中,一般上传的文件都要大于2M,这个问题也好解决,只需要在struts.xml中,配置一个constant常量,将文件的最大值设置成想要的。

<!-- 允许文件上传的大小,默认为2M 2097152 在这里设置成自己想要的-->
<constant name="struts.multipart.maxSize" value="2097152"></constant>

五、超出指定上传文件大小之后的提示

在项目中,往往有这种需求:当用户上传的文件大于系统设定的值的时候,需要提示用户,如果直接报错,用户体验非常不好。我在做这部分需求的时候,走了不少弯路,也查阅了大量的网上的资料,但是最终还是遇到了一个跨不过去的坑(对于我来说的,可能是自己知识储备不到位)。

我查阅了很多资料,都是说需要重写action中的addActionError方法,将上传文件的错误转变成action级别的错误,我这样做了,也在addActionError中获取到了相应的文件大小,将错误信息添加到supper.addActionError中之后,无论我如何,在jsp中也获取不到我自己抛出的错误信息,而是页面直接报错了。这个问题困扰了我很久,也跟一些人讨论过,但是最终还是没有一个完美的解释。于是,我想了一个比较笨的方法:

1、首先在constant中配置一个很大的最大值,这个值可以设置的大一点,我这里设置成了2000M

PS:我主要是最文档文件上传,也就是一些doc、pdf等,一帮不可能超过这么大。我系统中的需求是不能大于200M。

2、在文件上传的action中,获取上传上来的文件的大小,跟200M做一个比较,如果大于200M,那么将错误信息写到request作用域中,然后return error。否则正常执行文件上传的操作。对应代码中的位置:

// 声明文件的输入流,为输入流指定路径
FileInputStream is = new FileInputStream(file.get(i));
// 获取上传文件的大小(单位是字节1257114280--是1.17G),做数据狭小的限制,如果大于209715200,也就是200M,return
// error,提示上传文件大小不能超过200M,2097152--2M
int length = is.available();// 获取上传文件的字节大小
// 上传的文件超过200M
if (length >= 209715200) {
	
        request.setAttribute("error", "您上传的文件超过200M");
	return "error";
}
在错误页面中,使用struts的标签,得到自己抛出的错误信息,提示用户。

<s:property value="#request.error" />
PS:我这个测试demo是在SSH框架的基础上进行开发的,所以源码中会涉及到一些hibernate和spring相关的知识。


点我下载Demo


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值