【Struts2】文件的上传与上传权限的控制

很多关于Struts2的文章,对此都有详细的介绍,但是里面的示例的程序写得很糟糕。各种无意义的拦截器技术、国际化技术、初始化参数,把原本简单的程序弄得很繁琐。同时,部分关键的代码没有写。导致每次上传Tomcat都报Unable to find ‘struts.multipart.saveDir‘ property setting.的警告。然后上传大点的文件,整个Web工程就崩溃,然后后台抛出大段的File Upload BaseSize Limit Exceeded Exception异常,刷爆Tomcat。其实这些警告与异常都是可以避免的。我觉得程序就应该更加简短与丰满,而不是雍容华贵。下面举个例子来说明。


一、基本目标

利用Struts2制作一个文件上传系统,限制只能上传少于2M的图片,上传成功后就把图片的中文名、大小,与原本的图片显示。这图片保存到服务器的Upload文件夹。同时,扔一个再大的文件给这个系统,已不会找不到服务器。

技术分享


二、基本准备

与《【Struts2】Struts2纯手工安装、配置以及Helloworld,以最新版struts 2.3.20 GA做例子》(点击打开链接)一样准备好Struts2必须的jar,同时写好web.xml。这个不解释了。每次说Struts2都要引用一次这个文章。这次不用引入额外的包。

技术分享

配置好Struts2之后,目录结构如下,在里面新建两个文件夹,一个是未来存放上传文件的Upload,一个是Struts2要求的上传临时文件夹tmp,这个tmp没有也可以,只是会不停报Unable to find ‘struts.multipart.saveDir‘ property setting.的警告。写程序的时候,里面不用写任何东西。


三、制作过程

1、首先是upload.jsp,没什么好说的,就是一个文件表单。只是希望大家注意要对文件域设置好name,一会儿Struts2要根据这个名称接受文件,这里是file。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>选择文件</title>
</head>
<body>
	<form method="post" action="upload" enctype="multipart/form-data">
		选择文件:<input type="file" name="file" /><br />
		<input type="submit" value="上传" />
	</form>
</body>
</html>

2、uploaderr.jsp上传失败页面,这个主要是输出后台穿过来的错误信息。errMsg直接利用Jsp2.4的el表达式取就可以了,在《【Filter】利用过滤器Filter解决post传递的编码问题与利用EL表达式简化参数传递》(点击打开链接)已经提到过。不用像《【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示》(点击打开链接)利用到c标签,也就是JSTL表达式,更不用使用struts的s标签,就取个小小的值,不用这么复杂。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>上传失败</title>
</head>
<body>
上传失败!${errMsg}<br />
<a href="upload.jsp">返回</a>
</body>
</html>

3、上传成功页面uploadsuc.jsp,同理可得,取出服务器的上的保存名字构造出图片地址,后台传过来的文件名、文件大小,服务器上的保存文件名基本是一个时间戳,不可能给你存中文名的,但就算你要存中文名读取这张图片也没有问题,但是要用到《【Struts2】中文文件的下载与下载权限的控制》(点击打开链接)的技术

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>上传成功</title>
</head>
<body>
	上传成功!<br />
	文件:${fileFileName},大小:${fileLength}<br />
	<img src="./Upload/${saveFileName }" /><br />
	<a href="upload.jsp">返回</a>
</body>
</html>

4、struts.xml,这里虽然涉及到文件,但是按照往常一样指定处理的Action也就是java文件,设置根据返回结果跳转到什么链接就可以了。因为无须把文件抛回前台。主要是要在开头要设置两个属性,防止Tomcat抛出异常。也不要像某些书籍、文章那样设置什么拦截器、初始化参数什么的,半点意义没有。只会增加你的记忆负担而已。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC  
      "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
      "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<!-- 
	只是为了禁止上传时候弹出没有临时上传文件夹的警告! 
	实际上,这个临时上传文件夹没有也可以上传的。 
	不知道有什么用。 
	-->
	<constant name="struts.multipart.saveDir" value="/tmp" />
	<!-- 
	只是设置struts抛出文件过大异常的大小,这里设置成4G,因为FAT32最大的单文件就是4G
	struts2默认抛出文件过大异常的大小为2097152B也就是恰好2M,
	超过这个数会在Tomcat吐出一堆异常, 
	然后前台显示找不到页面,非常不友好。
	文件大小的控制不应该利用抛出异常控制,我们自己在java文件中控制就可以
	-->
	<constant name="struts.multipart.maxSize" value="4294967296" />
	<!-- 在test包里面 -->
	<package name="test" extends="struts-default">
		<!-- action为upload的执行方法就是test包中的upload.java中的run方法 -->
		<action name="upload" class="test.upload" method="run">
			<result name="success">/uploadsuc.jsp</result>
			<result name="error">/uploaderr.jsp</result>
		</action>
	</package>
</struts> 

5、upload.java这是我们核心处理Java,对比与《【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示》(点击打开链接)的利用一个Part对象处理完所有东西的Servlet3.0的文件上传,Struts2的文件上传,必须设置一个名称与前台页面传过来页面相同的File对象。在upload.jsp传来File对象的name="file"。因此就有一个File file的静态类成员。之后,Struts2会自动生成一个fileFileName,也就是文件域name属性+FileName的东西,给你包装好用户传递过来的文件名,注意那个N必须大写。当然还有一个name属性+ContentType的String对象给你封装文件类型,但是根本不用利用到这个对象,完全可以根据FileName中.的后缀名去确定文件类型。之后file.length()可以取出文件大小。

好了,这就可以对文件的上传权限进行控制。Struts2还要我们自己写文件存入服务器的方法。这段东西,没有什么解释。Java存文件就是这样存的。

package test;

//用到了输入流,必须的支持
import java.io.*;

//这个是为了取出Upload这个文件夹的绝对路径
import org.apache.struts2.ServletActionContext;

//这是Struts2必要的支持
import com.opensymphony.xwork2.ActionSupport;

//防止报序列号警告
@SuppressWarnings("serial")
//Struts2必须继承这个类
public class upload extends ActionSupport {
	//上传文件Action固有的两个属性fileContentType不是必须的
	//但一定要设置好getter与setter,这是Struts2固有的特点。
	//设置完getter与setter一定不可以在执行方法中再次初始化,如String xx=
	//这样前台会取不值的!
	private File file;
	private String fileFileName;
	//saveFileName是保存到服务器的名字
	//利用传来过的文件的后缀名+时间戳构造,
	//必要时还可以补上用户名
	private String saveFileName;
	//这是文件的大小,主要是为了传到前台
	private String fileLength;
	private String errMsg;

	//防止输入输出流报警告
	@SuppressWarnings("resource")
	public String run() throws Exception {
		//对错误信息字符串赋予""值,否则会返回前台一个null
		errMsg = "";
		//判断是否符合上传的条件
		boolean canUpload = true;
		//取出Upload的绝对路径
		String saveFilePath = ServletActionContext.getServletContext()
				.getRealPath("/Upload");
		//取出上传文件的后缀名
		String fileExtensions = getFileFileName().substring(
				getFileFileName().lastIndexOf("."));

		//根据后缀名判断是否能上传
		if (!(fileExtensions.equals(".gif") || fileExtensions.equals(".png")
				|| fileExtensions.equals(".jpeg")
				|| fileExtensions.equals(".jpg") || fileExtensions
					.equals(".bmp"))) {
			errMsg += "上传文件只能是图片,后缀名必须是bmp,gif,jpg,jpeg!";
			canUpload = false;
		}

		//根据文件大小判断是否能上传
		if (file.length() > (2 * 1024 * 1024)) {
			errMsg += "上传文件太大,请少于2M!";
			canUpload = false;
		}
		//把文件大小转化成字符串,推回给前台
		fileLength = (file.length() / 1024) + "KB";
	

		//如果可以上传
		if (canUpload) {
			//就营造一个服务器上的文件名
			saveFileName = System.currentTimeMillis() + fileExtensions;
			//输出流是保存到服务器的输出流
			FileOutputStream fos = new FileOutputStream(saveFilePath + "/"
					+ saveFileName);
			//输入流就是传过来的文件
			FileInputStream fis = new FileInputStream(getFile());
			//缓冲数组
			byte[] buffer = new byte[1024];
			int len = 0;
			//输入流不停读东西到缓冲数组,直到读完
			while ((len = fis.read(buffer)) > 0) {
				//输出流不停把缓冲数组的东西的东西写到服务器上Upload的绝对目录上面
				fos.write(buffer, 0, len);
			}
			//返回struts.xml一个成功结果
			return "success";
		} else {
			return "error";
		}
	}

	//所有静态成员必须有getter与setter,否则不能与前台交互
	public File getFile() {
		return file;
	}

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

	public String getFileFileName() {
		return fileFileName;
	}

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

	public String getSaveFileName() {
		return saveFileName;
	}

	public void setSaveFileName(String saveFileName) {
		this.saveFileName = saveFileName;
	}

	public String getErrMsg() {
		return errMsg;
	}

	public void setErrMsg(String errMsg) {
		this.errMsg = errMsg;
	}

	public String getFileLength() {
		return fileLength;
	}

	public void setFileLength(String fileLength) {
		this.fileLength = fileLength;
	}

}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。