您的位置:首页 > 编程语言 > Java开发

Struts2 入门学习笔记(五)——上传下载

2016-04-16 13:04 567 查看
Struts2 入门学习笔记(五)——上传下载

一.简介

首先要明确为了能进行上传,必须将表单设为POST,并且添加属性enctype="multipart/form-data",只有这样才能进行传送。当然,关于在struts.properties配置文件中关于上传时的上传解析器在此不做讲解,有想看的可以去配置文件查找,主要由以下三种,一般默认第三种:
#指定使用COS的文件上传解析器
#struts.multipart.parser=cos
#指定使用Pell的文件上传解析器
#struts.multipart.parser=pell
#指定使用Jakarta的Common-fileUpload文件上传解析器
#struts.multipart.parser=jakarta

二.单文件上传

1. 实现文件上传的Action首先写一个表单jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<s:form action="upload" enctype="multipart/form-data">
<s:textfield name="title" label="文件标题" />
<s:file name="upload" label="选择文件" />
<s:submit value="上传"/>
</s:form>
</body>
</html>
在struts2中框架负责解析HttpServletRequest请求的参数,包括文件域,Struts2使用File类型封装文件域,下面是Action:
package cn.sun.upload;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
 
import org.apache.struts2.ServletActionContext;
 
 
import com.opensymphony.xwork2.ActionSupport;
 
public class Upload extends ActionSupport{
//封装文件标题请求参数成员
private String title;
//封装上传文件域的成员变量
private File upload;
//封装上传文件类型
private String uploadContentType;
//封装上传文件名的属性
private String uploadFileName;
//直接在struts.xml中配置的成员变量
private String savePath;
//所有的getter/setter方法+下面这个(单独写是因为它的get是从struts.xml中取到的)
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
@Override
public String execute() throws Exception {
//以服务器的文件保存地址和原文件名简历上传文件输出流
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] buf = new byte[1024];
int len = 0;
while( ( len=fis.read(buf) ) > 0){
fos.write(buf, 0, len);
}
return SUCCESS;
}
}
下一步自然区设置配置文件,将这个action放入进去,同时将上面这个中savePath地址传入:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
 <package name="myPackage" extends="struts-default">
<action name="upload" class="cn.sun.upload.Upload">
<param name="savePath">/uploadFiles</param>
<result name="success">/page/success.jsp</result>
</action> 
 </package>
</struts>
这里顺便设置一个success页面用来显示接收到的文件:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
This is my success page!<br>
文件标题:<s:property value=" + title"/><br>
文件为:<img src="<s:property value="'uploadFiles/'+uploadFileName"/>"/><br>
</body>
</html>
上述中文件名一致没有变化,建议真正保存的时候一定要用UUID工具将文件名唯一化保存,同时放弃文件名中的格式,这样保存的就是一个不可执行不可预览文件,提取时通过uploadFileContentType去还原文件类型。文件不可轻易上传,有的文件万一有问题会影响系统的运行,或者有些东西是不允许上传的,或者文件大小要设限制等等,所以这里也需要一个过滤器来对上传文件进行一个过滤,通常有两种方法解决这个问题,一种是手动实现,在struts.xml文件中配置param放置允许上传类型,在action中提取后进行对比,有则上传,没有则返回异常或者错误界面;第二种是常见的过滤器设置,这里用拦截器实现文件的过滤,strtut2自带文件拦截器,我们只需要修改很少的代码就可以实现。。或者,还记得么,添加自己的拦截器,在自己的拦截器栈里加入自己的拦截器和默认拦截器栈,大功告成!这里使用struts自带的拦截器,在struts.xml中添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
 <package name="myPackage" extends="struts-default">
<action name="upload" class="cn.sun.upload.Upload">
<!-- 配置fileUpload的拦截器 -->
<interceptor-ref name="fileUpload">
<!-- 配置允许的上传文件类型 -->
<param name="allowedTypes">image/png,image/gif,image/jpeg</param>
<!-- 配置允许的上传文件大小 -->
<param name="maximumSize">200000</param>
</interceptor-ref>
<!-- 配置系统默认拦截器栈 -->
<interceptor-ref name="defaultStack" />
<!-- 添加属性 -->
<param name="savePath">/uploadFiles</param>
<result name="input">/page/fail.jsp</result>
<result name="success">/page/success.jsp</result>
</action> 
 </package>
</struts>
来一个失败页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head></head>
<body>
This is my fail page. <br>
<s:fielderror />
</body>
</html>
然后我们就可以去测定试一下了,结果上传成功

三.多文件上传

原理就是上面的那个,只不过多加了几次而已,这里只写几句话:
<title>Insert title here</title>
<script type="text/javascript">
function addFileUploadItem(){
var itemTdObj = document.getElementById("itemTdId");
//将原有的td中内容,添加一个字符串,设置回td
itemTdObj.innerHTML = itemTdObj.innerHTML + "<br/><span>选择文件:<input type=\"file\" name=\"image\" /></span>";
}
</script>
</head>
<body>
<!-- 使用JavaScript追加上传选择 -->
<a href="javascript:void(0)" onclick="addFileUploadItem()">添加上传选择</a>
<s:actionerror/>
<form action="${pageContext.request.contextPath}/uploadDemo02Action" method="post" enctype="multipart/form-data">
<table>
<tr>
<td id="itemTdId">
<span>选择文件:<input type="file" name="image" /></span>
</td>
</tr>
<tr>
<td><input type="submit" value="多文件上传"/></td>
</tr>
</table>
</form>
</body>
编写action提供字段及setter,接收多个文件时,需要提供数组获得。
//提供接收的数据类型是数组即可。
//#1 文件内容
private File[] image;
//#2文件名称
private String[] imageFileName;
//#3文件类型
private String[] imageContentType;
//#4 setter方法
public void setImage(File[] image) {
this.image = image;
}
public void setImageFileName(String[] imageFileName) {
this.imageFileName = imageFileName;
}
public void setImageContentType(String[] imageContentType) {
this.imageContentType = imageContentType;
}
public void add() throws Exception {
//父目录
String parentDir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/upload");
//遍历所有内容,并保存
for(int i = 0 ; i < image.length ; i ++){
// 1 文件内容
File singleImage = image[i]; 
// 2 文件名称
String singleFileName = imageFileName[i];
// 3 保存 
File file = new File(parentDir , singleFileName);
FileUtils.copyFile(singleImage, file);// (流自动关闭,父目录自动创建)
}
}
    提供国际资源文件    位置:当前类包下建立国际化文件/UploadDemo02Action.properties    内容:struts.messages.upload.error.SizeLimitExceededException=\u6587\u4EF6\u4E0A\u4F20\u5927\u5C0F\u8D85\u8FC7\u9650\u5B9A,\u5B9E\u9645\u5927\u5C0F{1}\uFF0C\u9650\u5B9A\u7684\u6700\u5927\u503C{0} properties文件的key固定的,来自 struts2-core-2.3.15.3.jar!/org/apache/struts2/struts-messages.properties

四.下载

下载实现比较简单,有许多种方法,但是为什么用struts呢,因为有很好的控制性,权限之类的问题。我们这里写一个实例来让大家明白下它的操作流程,首先编写action类:
package cn.sun.upload;
 
import java.io.InputStream;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class FileDownloadAction extends ActionSupport {
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//get方法在后面也有用
public InputStream getTargetFile() {
 
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
 
}
这里面我们定义了一个方法用来输出指定位置的文件流,只需要在其他地方使用该方法即可。配置action类型的结果需要制定以下四个属性:
contentType指定被下载文件的文件类型
inputName指定被下载文件的入口输入流
contentDisposition指定下载的文件名
bufferSize 下载缓冲大小
对应在struts.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
 <package name="myPackage" extends="struts-default">
<action name="download" class="cn.sun.upload.FileDownloadAction">
<param name="inputPath">/uploadFiles/1.jpg</param>
<result type="stream">
<!-- 指定下载文件类型 -->
<param name="contentType">image/jpg</param>
<!-- 指定由getTargetFile()方法返回被下载的文件inputstream流 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">attachment;filename=1.jpg</param>
<param name="bufferSize">4096</param>
</result>
</action>
 </package>
</struts>
中文乱码问题:        当我们希望下载中文的文件名时,和刚才不一样,刚才直接写死了下载的文件地址和文件名,一般情况下在action中应该这样写就可以避免乱码:
package cn.sun.upload;
 
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class FileDownloadAction extends ActionSupport {
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//////////////////////////////////////
private String imageFileName;
public String getImageFileName() throws UnsupportedEncodingException {
return new String(imageFileName.getBytes(),"ISO-8859-1");
}
/////////////////////////////////////
public InputStream getTargetFile() {
 
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
 
}
同理,在struts.xml中配置的时候刚才我们直接写得文件名,现在我们将获取到的文件名用表达式写出来而不是直接写汉语:
<action name="download" class="cn.sun.upload.FileDownloadAction">
<param name="inputPath">/uploadFiles/1.jpg</param>
<result type="stream">
<!-- 指定下载文件类型 -->
<param name="contentType">image/jpg</param>
<!-- 指定由getTargetFile()方法返回被下载的文件inputstream流 -->
<param name="inputName">targetFile</param>
<!--<param name="contentDisposition">attachment;filename=1.jpg</param>-->
<param name="contentDisposition">attachment;filename=${imageFileName}</param>
<param name="bufferSize">4096</param>
</result>
</action>
为什么我们在上面写一句${imageFileName}就可以收到文件名?这是因为在action中我们有一个getter方法,通过此方法就可以在xml中读取到数值,这是OGNL表达式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: