`
PerfectPlan
  • 浏览: 122491 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论
阅读更多

 

 关于struts2-上传与下载

 

一、struts2的上传下载是如何实现的?

:其实struts2框架中的下载是基于commons.fileupload.jar 和 commons.io.jar来实现的它只是将某些复

   杂的逻辑代码封装起来,并且简化从而利于开发者的开发。

二、struts2上传下载的核心是怎么样的?

  1.struts2上传下载的核心是由commons.fileupload中的ServletFileUpload和DiskFileItemFactory类

  来实现(在commons.fileupload.jar中以前的版本,主要使用的是FileUpload类。新的版本提倡使用   FileUpload的子类ServletFileUpload)

  2.DiskFileItemFacotry需要设置两个参数

   :Repository:创建一个文件上传的缓存目录

   SizeThreshold:设置在缓存中的文件大小

 

  3.ServletFileUpload实现它的一个有参构造方法

   :参数为FileItemFactory(它是一个接口) DiskFileItemFactory实现了这个接口

   :通过ServletFileUpload类的parseRequest()方法获取一个List<FileItem>集合,通过对集合的遍历解

    析获取表单中的信息

  4.下面提供一个以Servlet和jsp 使用commons.fileupload 和commons.io 实现的上传功能

   Servlet:(UploadServlet)

package org.viancent.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {
	@Override
	@SuppressWarnings("unchecked")
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*
		 * 注意,当jsp中表单的enctype设置的为:multipart/form-data的时候 我们无法直接使用
		 * request.getParameter("") 获取表单的数据信息
		 */
		// 使用DiskFileItemFacotry类进行表单的处理,以及文件的上传
		DiskFileItemFactory disk = new DiskFileItemFactory();
		// 获取WebRoot目录下的upload文件夹的路径
		String path = req.getRealPath("/upload");
		disk.setRepository(new File(path));// 设置上传文件的缓存目录
		disk.setSizeThreshold(1024 * 1024); // 设置文件的大小,如果超过这个大小,文件则会直接向硬盘存入

		// 借助ServletFileUpload 进行表单的解析,与文件的流的处理
		ServletFileUpload upload = new ServletFileUpload(disk);
		try {
			List<FileItem> list = upload.parseRequest(req);
			// List<FileItem>中保存着有关表单元素的所有信息 需要对它进行遍历
			for (FileItem item : list) {
				// item.isFormField() 判断该元素是不是表单的一个字段 如果是 则可以直接取得它的名称和内容
				if (item.isFormField()) {
					String name = item.getFieldName();
					/*
					 * 获取该字段的名称 如:<input type="text" name="password"/>
					 * 该方法便是获取name属性的值 :password
					 */
					String value = item.getString("gbk");
					/* 获取该字段的value属性的值 */
					req.setAttribute(name, value);
				} else// else则证明它是一个file文件流
				{
					String name = item.getFieldName();
					String value = item.getName();
					/*
					 * 对于表单中的file元素,我们不能通过getString获取它的内容,因为它是一个流
					 * 只能够通过getName方法获取当前文件的名称
					 */
					int start = value.lastIndexOf("\\");
					// 对value进行处理,由于某些浏览器 可能只显示 文件名+后缀
					// 有的则将文件的全部路径都显示出来 ,所以我们要在这里对它进行一次通用处理
					String filename = value.substring(start + 1);
					// 记住一定要将start+1 因为start的位置对应的是'\\'
					req.setAttribute(name, filename);
					// 创建输入流 与 输出流
					InputStream input = item.getInputStream();
					byte[] buffer = new byte[1024];
					int length = 0;
					OutputStream os = new FileOutputStream(new File(path,
							filename));
					// 开始读取并写入信息
					while ((length = input.read(buffer)) > 0) {
						os.write(buffer, 0, length);
					}
					// 一次关闭流
					os.close();
					input.close();
					// 上传完毕
					System.out.println("Upload Over!");
				}
			}
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 请求转发
		req.getRequestDispatcher("/upload/result.jsp").forward(req, resp);
	}
}

  Jsp:(upload.jsp)

<form action="/struts2/upload" method="post"
	enctype="multipart/form-data">
	//一定要设置form表单的 //method属性和enctype实行 UserName:<input type="text"
		name="username" id="username" /><br /> Password:<input type="password"
		name="password" id="password" /><br /> File: <input type="file"
		name="file" id="file" /><br /> <input type="submit" value="submit" />
</form>
 

  三、如何使用struts2封装后的上传与下载

: 1.上传

a):对于struts2中的上传主要是由struts-default.xml中名为:fileUpload的拦截器实现的通过拦截客户
端的请求,获取数据信息实现上传功能。
b):实现的主要步骤
1.我们需要创建一个对应上传的Action,在Action中我们需要定义三个字段用于存储表单中文件的信息
如下:
如果页面(<input type="file" name="upload">表单中的file元素名为:upload,那么我们需要在
Action中定义如下字段
private File upload; //对应文件流  根据表单的中的file元素的name属性值命名
private String uploadFileName;  //对应文件的名称 表单name属性值+FileName
private String uploadContentType; //对应文件的类型 表单name属性值+ContentType
/*命名规范是固定,并且要实现它们的getter 和 setter方法 可以参看fileUpload拦截器对应的
        Interceptor类中代码
主要用于拦截器为定义的属性进行赋值,以及后面的调用
*/
2.我们需要在struts.xml 文件中配置一个对应上传的<Action>
如下:
在定义的Action标签中需要添加名为 fileUpload的拦截器,并为它的属性进行赋值。
<interceptor ref="fileUpload">
//可以设置 上传文件的类型,最大大小,
/*
在FileUploadInterceptor 源代码中 有如下片段实例
 * <ul>
 * <p/>
 * <li>maximumSize (optional) - the maximum size (in bytes) that the interceptor will allow a file reference to be set
 * on the action. Note, this is <b>not</b> related to the various properties found in struts.properties.
 * Default to approximately 2MB.</li>
 * <p/>
 * <li>allowedTypes (optional) - a comma separated list of content types (ie: text/html) that the interceptor will allow
 * a file reference to be set on the action. If none is specified allow all types to be uploaded.</li>
 * <p/>
 * <li>allowedExtensions (optional) - a comma separated list of file extensions (ie: .html) that the interceptor will allow
 * a file reference to be set on the action. If none is specified allow all extensions to be uploaded.</li>
 * </ul>
			 
 maximumSize:设置单个上传文件的最大字节,struts2中默认的总上传文件的大小为2097152字节(2M) 我们可以通过
 <Constant name="struts.multipart.maxSize" value="">value指定大小 ,单位为字节
 allowedTypes:设置上传文件的类型 上传的文件类型可以参考tomcat中web.xml配置中的文件类型信息
 属性值 如:application/vnd.ms-powerpoint 代表文件的类型为ppt
 allowedExtensions:设置文件的扩展名,同上一个属性的效果是一样的,不过它的属性值更加
 直观易懂 如: .ppt 
 */	
 <param name="allowedExtensions">.ppt,.txt</param>//使用<param>标签进行赋值
 <param name="maximumSize">409600</param>//上传单个文件的最大字节
 </interceptor ref>
 3.一个使用struts2的上传实例:
Action:
package org.viancent.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport {

	private String username;
	private String password;
	/*
	 * 如果每次只上传一个文件 就可以使用上面介绍的代码
	 * 
	 * 这里义的泛型集合,是为了上传多个文件,也可以用数组 如:
	 *  privaet File [] file;
	 * private String [] fileFileName;
	 * private String [] fileContentType;
	 */
	private List<File> file;
	private List<String> fileFileName;
	private List<String> fileContentType;

	/*
	 * 为什么要定义fileFileName 和filecontextType 这里是用于FileUpload的拦截器的赋值
	 */
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	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;
	}

	@Override
	public String execute() throws Exception {
		// 指定上传的位置
		String path = ServletActionContext.getRequest().getRealPath("/upload");
		for (int i = 0; i < file.size(); i++) {
			// 获取输入流
			InputStream is = new FileInputStream(file.get(i));
			byte[] buffer = new byte[1024];
			int length = 0;
			// 创建输出流对象
			OutputStream os = new FileOutputStream(new File(path, this
					.getFileFileName().get(i)));
			// 开始上传
			while ((length = is.read(buffer)) > 0) {
				os.write(buffer, 0, length);
			}
			// 一次关闭流
			os.close();
			is.close();
		}
		// 返回结果
		return SUCCESS;
	}
}
  View : upload2.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'upload2.jsp' starting page</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">

<script type="text/javascript">
							function addMore() //触发此方法后添加一个,file元素
							{
							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 ()//为Remove按钮注册一个点击事件
							{
								td.removeChild(br);
								td.removeChild(input);
								td.removeChild(button);
								}
							td.appendChild(br);
							td.appendChild(input);
							td.appendChild(button);
								}
						</script>
</head>
<body style="text-align: center">

	<div style="text-align: left">
		<s:fielderror cssStyle="color:red"></s:fielderror>
		<s:actionerror />
	</div>
	<s:form action="upload" method="post" enctype="multipart/form-data"
		theme="simple">
		<table border="1" width="80%">
			<tr>
				<td>UserName:</td>
				<td><s:textfield name="username"></s:textfield></td>
			</tr>
			<tr>
				<td>PassWord:</td>
				<td><s:password name="password"></s:password></td>
			</tr>
			<tr>
				<td>File1:</td>
				<td id="more"><s:file name="file"></s:file> <input
					type="button" value="Add More" onclick="addMore()"></td>
			</tr>
			<tr>
				<td><s:submit value="Submit"></s:submit></td>
				<td></td>
			</tr>

		</table>
	</s:form>
</body>
</html>

  struts.xml的配置信息

				<struts>

					<constant name="struts.multipart.saveDir" value="e:\"></constant>//设置缓存文件的存放位置(当上传完成后,会被自动删除)
					<constant name="struts.i18n.encoding" value="gbk"></constant> //设置编码格式
					<constant name="struts.custom.i18n.resources" value="message"></constant>//当上传失败的时候,可以在指定的message.properties中定义显示的错误信息

					<package name="struts2" extends="struts-default">

						<action name="upload" class="org.viancent.action.UploadAction">
							<result name="success">/upload/result.jsp</result>
							<result name="input">/upload/upload2.jsp</result>

							<interceptor-ref name="fileUpload">
								<param name="allowedExtensions">.ppt,.txt</param>
								<param name="maximumSize">409600</param>
							</interceptor-ref>
							<interceptor-ref name="defaultStack"></interceptor-ref>
						</action>
					</package>
				</struts>

 

//当上传的文件太大,或者文件类型不符合规定的时候我们可以自定义一个资源文件
//根据struts-message.properties中的默认属性名 在自己定义的资源文件中给这些属性重新赋值
struts.messages.error.file.too.large=File too large: {0} "{1}" "{2}" {3}
//当文件太大的时候抛出的错误信息
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
//文件类型不符合规定的时候抛出的错误信息
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
//当文件的扩展名不符合规定的时候抛出的错误信息
//注意这些错误都是FieldError级别的 如果希望在页面上显示,那么就要使用 <s:fielderror>标签
 

4.介绍一下关于defalut.properties 中的struts.multipart.maxSize 和 fileUpload中的

maximumSize的区别!

 

1.struts.multipart.maxSize掌控整个项目所上传文件的最大的Size。超过了这个size,后台报

错,程序处理不了如此大的文件。ActionError里面会有如下的提示:

the request was rejected because its size (16272982) exceeds the configured

maximum (9000000)

 

2.fileUpload拦截器的maximumSize属性必须小于struts.multipart.maxSize的值。

struts.multipart.maxSize默认2M,当maximumSize大于2M时,必须设置

struts.multipart.maxSize的值大于maximumSize。

 

3.当上传的文件大于struts.multipart.maxSize时,系统报错

当上传的文件在struts.multipart.maxSize和maximumSize之间时,系统提示:

File too large: file "MSF的

 

 

2.下载

a):关于下载主要是有struts-default.xml中的<result-type name="stream"

class="org.apache.struts2.dispatcher.StreamResult"/>来完成的

所以我们只需要设置struts.xml中对应下载的<action>中的<result type="">的type属性 将它设置成:

stream。

1.为stream对应的org.apache.struts2.dispatcher.StreamResult.class类的属性进行赋值主要有

如下属性:

 

//StreamResult类中的字段源码
/*
			protected String contentType = "text/plain";//设置下载文件的类型
			protected String contentLength;				//设置文件的大小
			protected String contentDisposition = "inline";	//设置下载的时候显示的文件名
			protected String contentCharSet ;				//设置编码格式
			protected String inputName = "inputStream";		
			//设置对应下载的Action类中获取java.io.InputStream的类的名称 在Action中该类的名称最好为:
			// public InputStream getInputStream(){}
			protected int bufferSize = 1024;	//设置下载缓冲大小		
*/

       2.具体实例如下:

struts.xml:

						
						<action name="download" class="org.viancent.action.DownloadAction">
							<result name="success" type="stream">
								
								<param name="contentType">application/vnd.ms-powerpoint</param>//这里的赋值方式 与 fileUploadInterceptor的allowedTypes方式相同
								<param name="contentDisposition">filename="${fileNames}"</param>
								/*
									${fileNames} 这个el表达是是为了获取Action中 getFileNames()方法的返回值
									该方法是为了解决文件乱码实现的
								*/
								<param name="inputName">inputStream</param>
								/*
									inputStream 是为了获取对应Action 中的getInputStream()方法的返回值
									该返回值的类型为 java.io.InputStream
								*/
								<param name="bufferSize">4096</param>
								
							</result>
						</action>

 Action:

package org.viancent.action;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction extends ActionSupport {

	private String pathName; // 该字段是为了获取页面传过来的文件名称的信息

	public String getPathName() {
		return pathName;
	}

	public void setPathName(String pathName) {
		this.pathName = pathName;
	}

	public String getFileNames() throws Exception {
		// 返回文件的名称 给<param
		// name="contentDisposition">filename="${fileNames}"</param>
		return this.getPathName();
	}

	public InputStream getDownload() throws Exception {
		// 这里是一个重点 获取一个输入流
		return ServletActionContext.getServletContext().getResourceAsStream(
				"/upload/"/* 获取WebRoot/upload/的某一个文件 */
						+ new String(this.getPathName().getBytes("iso-8859-1"),
								"gb18030"));
		// new String(this.getPathName().getBytes("iso-8859-1"),"gb18030")
		// 将文件名进行转码 转换成简体中文
		// 当没有找到该文件对象的时候 会抛出
		/*
		 * Can not find a java.io.InputStream with the name [download] in the
		 * invocation stack. Check the <param name="inputName"> tag specified
		 * for this action.
		 */
	}

	@Override
	public String execute() throws Exception {
		return SUCCESS;
	}
}

  Jsp (upload2.jsp)

<a href="/struts2/download.action?pathName=第四讲.ppt">下载一</a>
<a href="/struts2/download.action?pathName=12.txt">下载二</a>
/*
pathName=第四讲.ppt
对Action中的pathName属性进行赋值,用于指定下载哪一个文件
*/
5
3
分享到:
评论
3 楼 PerfectPlan 2012-06-17  
fancy2010love 写道
// 获取WebRoot目录下的upload文件夹的路径 
29.  String path = req.getRealPath("/upload"); 
req.getRealPath这个方法已经过时了,应该不建议再使用吧

嗯嗯,是不建议是用了。以前写的,谢谢建议哦
2 楼 fancy2010love 2012-06-17  
String path = request.getSession().getServletContext().getRealPath("/upload")
这个方法应该可以吧
1 楼 fancy2010love 2012-06-17  
// 获取WebRoot目录下的upload文件夹的路径 
29.  String path = req.getRealPath("/upload"); 
req.getRealPath这个方法已经过时了,应该不建议再使用吧

相关推荐

    Struts2-2.3.16 全jar包

    支持Struts2 搭框架中基本上最常用的所有的jar包。 我用的是struts2.2.3.16(不管用struts2的哪个版本,道理都一样,找对应的包就行了) 例如你建一Web Project,名为Struts2 导入项目所需要的jar包,放入/Struts2/...

    struts-2.5.22-all.zip

    除此之外,Struts2还依赖于其他一些库,如OGNL(Object-Graph Navigation Language)用于表达式语言,Freemarker或Velocity用于视图模板,以及各种插件来支持特定的功能,如文件上传、JSON处理等。 在标签中提到了...

    struts2-core-2.3.31.jar

    该漏洞与Apache Struts2 (S2-045)远程代码执行漏洞原理基本相同,均是由于上传功能的异常处理函数没有正确处理用户输入的错误信息,导致远程攻击者可通过发送恶意的数据包,利用该漏洞在受影响服务器上执行任意...

    struts2-blank-2.0.14的lib中的jar包

    - `servlet-api.jar`: Servlet API,Struts2与Servlet容器交互的接口定义。 - `jsp-api.jar`: JSP API,用于JSP页面的处理。 这些jar包共同构成了Struts2框架的运行环境,让开发者可以专注于业务逻辑的实现,而...

    struts2-core-2.1.8.1.jar

    在压缩包子文件的文件名称列表"struts_jar"中,很可能包含的是与Struts2相关的所有依赖库,便于构建一个完整的Struts2应用环境。使用这样的集合可以快速搭建Struts2项目,并确保所有必要的库都已就绪。 总结来说,...

    struts2漏洞s2-045,不升级jar版本的修补方法,已验证.docx

    2. 下载对应版本的源码包:接下来,我们需要下载对应版本的源码包,例如下载 struts2-core-2.3.16.1-sources.jar。 3. 解压找到位置 org/apache/struts2/dispatcher/multipart:然后,我们需要解压源码包,找到 org...

    struts2-blank.war

    这里上传的是struts-2.3.37-all里面的空白模板struts2-blank,解压后里面有Struts2运行所需要的基础jar包

    struts2-dojo-plugin-2.1.2.jar

    struts2-dojo-plugin-2.1.2.jar CSDN大多下载不了,所以上传!

    struts2-core-2.5.10.1

    修复S2-045:Struts 2远程执行代码漏洞,时用到的jar,漏洞影响:基于Jakarta Multipart解析器执行文件上传时可能的RCE 影响版本:Struts 2.3.5 - Struts 2.3.31  Struts 2.5 - Struts 2.5.10

    struts2-2.2.3-all.zip

    样例通常包含了一些基础的功能实现,如表单验证、文件上传下载、拦截器使用等,可以帮助开发者快速上手并理解Struts2的基本用法。通过研究这些样例,开发者可以学习到如何配置Struts2、如何编写Action类、如何使用...

    struts2-lib

    - `struts2-freemarker-plugin`: 这个插件将Freemarker与Struts2集成,提供对Freemarker模板的支持。 3. **插件**: - `struts2-convention-plugin`: 自动配置插件,根据类名和方法名自动映射Action。 - `struts...

    Struts2VulsTools-Struts2系列漏洞检查工具

    该工具的打开路径为:\Struts2VulsTools-2.3.20190927\Test\bin\Release\Text.exe 2019-09-25: 优化部分EXP在部分情况下被WAF拦截的问题,提高检测成功率,优化自定义上传路径exp,文件所在目录不存在时自动创建...

    struts2-demo

    struts2-core-2.x.x.jar : Struts2 框架的核心类库 b. xwork-core-2.x.x.jar: XWork类库,Struts2在其上构建 c. ognl-2.6.x.jar: 对象图导航语言(Object Graph Navigation Language),Struts2框架通过其读写对象的...

    struts2-upload-jar

    Struts2-upload-jar是Apache Struts框架的一个插件,主要功能是支持文件上传和下载。Struts2作为Java EE领域中的一个流行MVC(Model-View-Controller)框架,为开发者提供了处理用户请求、展示视图以及业务逻辑集成...

    [原]Struts2-文件上传与下载

    在Struts2中,文件上传和下载是常见的功能需求,它们对于用户交互性至关重要,例如用户提交表单时上传图片或文档,或者系统提供文件资源下载服务。本篇文章将深入探讨Struts2中的文件上传和下载机制。 首先,我们来...

    struts框架-文件上传下载

    2. Struts2中的文件上传:Struts2提供了更简洁的文件上传方式。在JSP页面中,可以使用`&lt;s:file&gt;`标签来创建文件选择控件。在Action类中,使用`@SkipValidation`注解标记文件上传方法,然后定义对应的`java.io.File`...

    burplugin-java-rce:******本软件仅用于学习交流禁止用于任何非法行为******本版本支持elasticsearch java语言远程命令执行及文件上传elasticsearchgroov语言远程命令执行及文件上传struts2-005, struts2-009,struts2-013,struts2-016,struts2-019,struts2-020,struts2-devmode,struts2-032,struts2-033,struts2-037,struts2-045,

    本版本支持elasticsearch java语言远程命令执行及文件上传elasticsearchgroov语言远程命令执行及文件上传struts2-005,struts2-009,struts2-013,struts2-016,struts2-019,struts2-020,struts2-devmode,struts2...

    struts-2.5.14-最核心的文件jar

    在Struts2中,它用于处理文件上传和下载等操作。 9. **commons-fileupload-1.3.3.jar**:Apache Commons FileUpload是处理HTTP多部分表单数据的库,常用于处理用户上传的文件。在Struts2中,结合commons-io库,实现...

    struts2-apps.rar

    - 这个压缩包中的"apps"目录可能包含各种Struts2的示例应用,例如登录注册、CRUD操作、文件上传下载等。 - 通过分析这些示例,学习者可以了解如何实际配置和使用Struts2的各种特性。 8. **学习与实践**: - 分析...

Global site tag (gtag.js) - Google Analytics