struts2文件上传与下载

本文介绍Struts2框架中的文件上传与下载功能实现。包括使用FileUpload拦截器进行文件上传,设置最大文件大小及文件类型限制,并展示如何配置错误处理。此外,还详细说明了如何利用StreamResult完成文件下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:Struts2文件上传

企业常用文件上传技术 : jspSmartUpload(主要应用 JSP model1 时代) 、 fileupload (Apache commons项目中一个组件)、 Servlet3.0 集成文件上传 Part类。Struts2 对文件上传的支持, 提供 FileUpload 拦截器,用于解析 multipart/form-data 编码格式请求,解析上传文件的内容 。fileUpload拦截器 默认在 defaultStack 栈中, 默认会执行的 。         
文件上传  enctype="multipart/form-data"  是 MIME协议定义多部分请求体 (消息体)。上传页面中存在 <input type="file" name="upload"/> 上传项,必须提供name属性。表单提交方式 必须 post 提交。表单编码类型 enctype="multipart/form-data"  。
下面是struts2完成文件上传的例子:
页面如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>    
<!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>Insert title here</title>
</head>
<body>
<h1>上传页面</h1>
<s:actionerror/>
<s:fielderror />
<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath }/upload.action">
	上传文件 <input type="file" name="upload" />
	<input type="submit" value="上传" />
</form>
</body>
</html>
Action如下:我们保存的服务器的upload文件夹下:

public class UploadAction extends ActionSupport {
	// 接收上传内容
	// <input type="file" name="upload" />
	private File upload; // 这里变量名 和 页面表单元素 name 属性一致
	private String uploadContentType;//上传表单项name属性 + ContentType
	private String uploadFileName;//上传表单项name属性 + FileName

	public void setUpload(File upload) {
		this.upload = upload;
	}

	public void setUploadContentType(String uploadContentType) {
		this.uploadContentType = uploadContentType;
	}

	public void setUploadFileName(String uploadFileName) {
		this.uploadFileName = uploadFileName;
	}

	@Override
	public String execute() throws Exception {
		if (upload == null) { // 通过xml配置 required校验器 完成校验
			// 没有上传文件
			return NONE;
		}
		// 将上传文件 保存到服务器端
		// 源文件 upload
		// 目标文件
		File destFile = new File(ServletActionContext.getServletContext()
				.getRealPath("/upload") + "/" + uploadFileName);
		// 文件复制 使用commons-io包 提供 工具类
		FileUtils.copyFile(upload, destFile);
		return NONE;
	}
}
Action的配置文件如下:
<?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.devMode" value="true" />
	<!-- 文件上传总大小,这是全局配置,对所有上传Action都生效 -->
	<constant name="struts.multipart.maxSize" value="20000000"></constant>

	<package name="basicstruts2" extends="struts-default">
		
		<!-- 文件上传 -->
		<action name="upload" class="fly.sun.demo.UploadAction">
			<!-- 上传错误页面 -->
			<result name="input">/demo1/upload.jsp</result>
			
			<!-- 设置上传参数 -->
			<interceptor-ref name="defaultStack">
				<!-- 只允许上传 mp3和txt文件 -->
				<param name="fileUpload.allowedExtensions">.mp3,.txt</param>
				<!-- 当前form 上传文件大小限制,会覆盖上面的全局配置 -->
				<param name="fileUpload.maximumSize">6000000</param>
			</interceptor-ref>
		</action>
		
	</package>

</struts>
Struts2 上传文件过程中错误处理
配置 input 视图 ,作为上传出错后 跳转页面 。在文件上传时,如果发生错误 ,fileUpload拦截器会设置错误信息,workflow拦截器 跳转到 input 视图。
struts.multipart.parser=jakarta 定义文件上传,采用 commons-fileupload 技术 ,同时支持 cos 、pell 上传技术 (如果使用其它上传技术,单独下载jar包 )。
通过 struts.multipart.maxSize 常量设置文件上传总大小限制 
 * struts.multipart.maxSize=2097152 默认上传文件总大小 2MB 
 * 超过文件总大小,跳转input 视图, 通过 <s:actionError /> 回显错误信息 
在struts.xml 设置上传总大小,<constant name="struts.multipart.maxSize" value="20000000"></constant>
设置上传文件总大小,对所有上传form有效只想对当前form进行设置,可以设置fileUpload拦截器属性 ,见上面action的配置文件配置。
FileUpload 拦截器有 3 个属性可以设置.
* maximumSize: 上传文件的最大长度(以字节为单位), 默认值为 2 MB
* allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔
* allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔
如果针对fileUpload 进行参数设置,当出错时,在页面通过 <s:fieldError /> 回显错误信息 

struts-messages.properties 文件里预定义上传错误信息,通过覆盖对应key 显示中文信息
struts.messages.error.uploading=Error uploading: {0}
struts.messages.error.file.too.large=The file is to large to be uploaded: {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}
在action所在的包下定义action名称.properties。将上述默认配置修改为下方中文提示以覆盖:
struts.messages.error.uploading=上传错误: {0}
struts.messages.error.file.too.large=上传文件太大: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=上传文件的类型不允许: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=上传文件的后缀名不允许: {0} "{1}" "{2}" {3}

二:文件下载

1) struts2 完成文件下载,通过 结果集类型 (Result Type) stream 来完成的 
struts-default.xml 定义 <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
2) 使用Stream结果集 完成文件下载 
文件下载原理: 服务器读取下载文件内容,通过Response响应流写回, 设置 ContentType、 ContentDisposition 头信息
public class StreamResult extends StrutsResultSupport {
protected String contentType = "text/plain"; //
contentType头信息  (下载文件对应 MIME协议规定类型 )
* html --- text/html . txt--- text/plain 
protected String contentDisposition = "inline"; // ContentDisposition头信息 (下载文件打开方式 inline浏览器内部打开, attachment 以附件形式打开)
protected String inputName = "inputStream";  // 需要Action中 提供 getInputStream 方法 返回 InputStream 提供下载文件 内容 
}
Action 提供 InputStream  返回值 getInputStream 方法 ------- 指定下载文件流
配置 stream 结果集 参数 <param name="contentType">${contentType}</param> ---- 在Action 中提供 getContentType
*  ServletActionContext.getServletContext().getMimeType(filename);
配置 stream 结果集 参数 <param name="contentDisposition">attachment;filename=${filename}</param> ---- 在Action 提供 getFilename 
* 下载附件名乱码问题 , IE和火狐 解决不同 
public String encodeDownloadFilename(String filename, String agent)
throws IOException {
if (agent.contains("Firefox")) { // 火狐浏览器
filename = "=?UTF-8?B?"
+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
+ "?=";
} else { // IE及其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}

下面直接上代码:
download.jsp页面
<%@ 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>Insert title here</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/download.action?filename=struts笔记.txt">struts笔记</a>
<a href="${pageContext.request.contextPath }/download.action?filename=Struts2上传下载.ppt">Struts2上传下载.ppt</a>
<a href="${pageContext.request.contextPath }/download.action?filename=哈哈.mp3">哈哈.mp3</a>
</body>
</html>
Action:
public class DownloadAction extends ActionSupport {
	private String filename;

	public void setFilename(String filename) throws IOException {
		// 解决文件名 get方式提交 乱码
		this.filename = new String(filename.getBytes("ISO-8859-1"), "utf-8");
	}

	@Override
	public String execute() throws Exception {
		System.out.println("下载:" + filename);
		// 文件下载 结果集 是一个流
		return SUCCESS;
	}

	// 提供 下载文件 流
	// 因为StreamResult中 protected String inputName = "inputStream";
	public InputStream getInputStream() throws IOException {
		// 下载文件输入流
		File file = new File(ServletActionContext.getServletContext()
				.getRealPath("/download") + "/" + filename);
		return new FileInputStream(file);
	}

	// 根据下载文件名动态获得 MIME文件类型
	public String getContentType() {
		// 读取tomcat/conf/web.xml
		return ServletActionContext.getServletContext().getMimeType(filename);
	}

	// 下载附件名 ${filename}
	public String getFilename() throws IOException {
		// 附件名乱码 问题 (IE和其它浏览器 : URL编码 , 火狐: Base64编码)
		String agent = ServletActionContext.getRequest()
				.getHeader("user-agent");
		return encodeDownloadFilename(filename, agent);
	}

	/**
	 * 下载文件时,针对不同浏览器,进行附件名的编码
	 * 
	 * @param filename
	 *            下载文件名
	 * @param agent
	 *            客户端浏览器
	 * @return 编码后的下载附件名
	 * @throws IOException
	 */
	public String encodeDownloadFilename(String filename, String agent)
			throws IOException {
		if (agent.contains("Firefox")) { // 火狐浏览器
			filename = "=?UTF-8?B?"
					+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
					+ "?=";
		} else { // IE及其他浏览器
			filename = URLEncoder.encode(filename, "utf-8");
		}
		return filename;
	}
}
action配置:
<!-- 文件下载 -->
		<action name="download" class="cn.itcast.struts2.demo2.DownloadAction">
			<result type="stream">
				<!-- 使用默认流 名称 inputStream, 设置两个头 -->
				<!-- 应该根据文件名 动态获得 MIME类型 -->
				<!-- 在Action 提供 getContentType方法根据下载文件名动态获得 MIME文件类型 -->
				<param name="contentType">${contentType}</param>
				
				<!-- 解析下载附件名 问题-->
				<param name="contentDisposition">attachment;filename=${filename}</param>
			</result>
		</action>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值