Struts2的文件上传
原理:由默认的拦截器栈中的FileUpload 拦截器来完成文件的上传工作
前提: 1. HTML 表单的 enctype 属性设置为 multipart/form-data,
2. Form表单的提交方式,Method 属性设置为 post
3. 程序员必须提供一个 <input type=“file”> 字段. 必须得有name属性
案例:
步骤1:搭建 Struts2的开发环境.
步骤2: 在webroot下新建一个jsp
JSP页面为:
<h1>文件上传</h1>
<form action="${ pageContext.request.contextPath }/upload.action" method="post" enctype="multipart/form-data">
文件上传:<input type="file" name="upload"/><br/>
<input type="submit" value="上传">
</form>
步骤3:编写一个UploadAction.
public class UploadAction extends ActionSupport {
private File upload; // 上传的文件
private String uploadContentType;// 文件的MIME类型
private String uploadFileName; // 文件名.
public void setUpload(File upload) {
this.upload = upload;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String execute() throws Exception {
System.out.println("UploadAction....");
// 获得服务器端的上传的路径. 获得 upload 磁盘绝对路径.
String path = ServletActionContext.getServletContext().getRealPath(
"/upload");
File file = new File(path + "/" + uploadFileName);
// FileUtils.copyFile(); --- 完成 文件上传.
FileUtils.copyFile(upload, file);
return NONE;
}
步骤4:在strtus.xml 中 配置 Action
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.multipart.maxSize" value="20000000" />
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
<package name="demo1" extends="struts-default">
<!-- 文件上传的Action -->
<action name="upload" class="cn.itcast.struts2.demo1.UploadAction">
<result name="input">/demo1/upload.jsp</result>
<!-- 配置一个拦截器 -->
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">2000000</param>
<param name="fileUpload.allowedExtensions">.jpg,.mp3</param>
</interceptor-ref>
</action>
<!-- 配置多文件上传的Action -->
<action name="multiUpload" class="cn.itcast.struts2.demo1.MultiUploadAction">
<result name="input">/demo1/multi_upload.jsp</result>
</action>
</package>
</struts>
* 步骤5: 编写Action中的代码.
* 提供三个成员变量:
private File upload; // 上传的文件
private String uploadContentType;// 文件的MIME类型
private String uploadFileName; // 上传文件名.
* 对三个属性 提供相应的set方法.
* 步骤6:在Action的execute方法中
String path = ServletActionContext.getServletContext().getRealPath("/upload");
File file = new File(path + "/" + uploadFileName);
// FileUtils.copyFile(); --- 完成 文件上传.
FileUtils.copyFile(upload, file);
二.关于在文件上传中错误的处理:
错误:拦截器
<interceptor name=”fileUpload class=”org.apache.struts2.interceeptor.FileUploadInterceptor”/> 这个拦截器帮助实现文件上传。
在默认拦截器栈中
<interceptor-stack name =”defaultStack”>
<interceptor-ref name=”fileUpload”/>
<interceptor-ref name=”workflow”>
<param name=”excludeMethods”>input,vback,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
跳转到input逻辑视图
在struts2的默认设置中,文件大小为2M
常量:struts.multipart.maxSize=2097152
修改常量:strtus2.xml
<constant name=”struts.multipart.maxSize” value=”200000” /> 直接写在struts标签下面代表所以页面上传的大小控制;
* 针对某个表单 设置文件的上传的大小.
* 使用 拦截器. Ctrl+shift+T 找见fileupload拦截器的实现类,看源代码,有属性
maximumSize: 上传文件的最大长度(以字节为单位), 默认值为 2 MB
allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔
* 常见的MIME类型: text/plain --- txt text/html --- html
allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔
在struts.xml中:
<package name="demo1" extends="struts-default">
<!-- 文件上传的Action -->
<action name="upload" class="cn.itcast.struts2.demo1.UploadAction">
<result name="input">/demo1/upload.jsp</result>
<!-- 配置一个拦截器 -->
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">2000000</param>
<param name="fileUpload.allowedExtensions">.jpg,.mp3</param>
</interceptor-ref>
</action>
<!-- 配置多文件上传的Action -->
<action name="multiUpload" class="cn.itcast.struts2.demo1.MultiUploadAction">
<result name="input">/demo1/multi_upload.jsp</result>
</action>
</package>
三.修改错误信息的提示: 在org.apache.struts2包下 struts-message.properties中
国际化: 写个与action同名的属性文件, UploadAction.properties
把key复制过来, 写入自己的提示信息;
在jsp页面中, 写标签: <s:actionerror/>
<s:fielderror/>
引入标签 <%@ taglib uri="/struts-tags" prefix="s"%>
三.多文件的上传步骤
Jsp页面:
<h1>多文件上传</h1>
<s:actionerror/>
<s:fielderror/>
<form action="${ pageContext.request.contextPath }/multiUpload.action" method="post" enctype="multipart/form-data">
文件上传:<input type="file" name="file"><br/>
文件上传:<input type="file" name="file"><br/>
文件上传:<input type="file" name="file"><br/>
<input type="submit" value="上传">
</form>
写action
1.写三个属性;
private File[] file;
private String[] fileContentType;
private String[] fileFileName;
2.生成set方法
3.在方法中写
public String execute() throws Exception {
// 获得upload下的磁盘绝对路径
String path = ServletActionContext.getServletContext().getRealPath(
"/upload");
for (int i = 0; i < file.length; i++) {
File f = new File(path + "/" +fileFileName[i]);
FileUtils.copyFile(file[i], f);
}
return NONE;
}
配置struts.xml文件
<!-- 配置多文件上传的Action -->
<action name="multiUpload" class="cn.itcast.struts2.demo1.MultiUploadAction">
<result name="input">/demo1/multi_upload.jsp</result>
</action>
四.Strtuts2的文件下载
文件下载: 将服务上的文件 copy 本地计算机. 获得服务器上文件的输入流 用 response 的 字节流 写到浏览器.
* 设置两个头
* ContentType 文件 MIME类型.
* ContentDisposition attachment; --- 以附件形式打开.
* 一个流 两个头.
Struts2中 文件下载的话 提供了一个 result的 类型.
* <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
在strtus.xml中进行配置:
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename=${filename}</param>
</result>
需要在Action中提供
public String getContentType(){
}
public String getFilename(){
}
public InputStream getInputStream(){
}
具体步骤:1. Jsp页面
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>文件下载的页面</h1>
<a href="${ pageContext.request.contextPath }/download.action?filename=JavaEE物联云计算就业班.xls">JavaEE物联云计算就业班.xls</a><br/>
<a href="${ pageContext.request.contextPath }/download.action?filename=侯磊-味道.mp3">侯磊-味道.mp3</a><br/>
<a href="${ pageContext.request.contextPath }/download.action?filename=3.jpg">3.jpg</a>
</body>
</html>
2.action的内容
1. 接收数据,通过属性驱动(定义个传的参数, 提供set方法)
// 接收数据
private String filename;
public void setFilename(String filename)
throws UnsupportedEncodingException {
this.filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8"); // 编码转换
}
// 提供一个方法
// 获得文件的MIME类型. contentType
public String getContentType() {
return ServletActionContext.getServletContext().getMimeType(filename);
}
// 提供一个获得文件名的方法
// 下载的文件名没有中文.有中文: IE URL 编码 FireFox 采用 base64编码.
public String getFilename() throws IOException {
// 获得浏览器类型:User-Agent
String agent = ServletActionContext.getRequest()
.getHeader("User-Agent");
return encodeDownloadFilename(filename, agent);
}
// 提供一个获得流的方法
public InputStream getInputStream() throws FileNotFoundException {
// 获得download 磁盘绝对路径
String path = ServletActionContext.getServletContext().getRealPath(
"/download");
File file = new File(path+"/"+filename);
return new BufferedInputStream(new FileInputStream(file));
}
/**
* 下载文件时,针对不同浏览器,进行附件名的编码
*
* @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;
}
2.配置struts.xml,设置result类型为stream
<package name="demo2" extends="struts-default">
<!-- 文件下载 -->
<action name="download" class="cn.itcast.struts2.demo2.DownloadAction">
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename=${filename}</param>
</result>
</action>
</package>
可以查看源代码, 就是stream那个拦截器, 进去有默认的类型,需要设置