一: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}
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 提供下载文件 内容
}
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;
}
下面直接上代码:配置 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>