一、它能做什么?

借助于这个拦截器我们可以实现文件的上传和下载功能。

理论部分:

struts2的文件上传下载功能也要依赖于Apache commons-fileupload和Apache commons-io两个开源项目,要使用上传功能就需要把它们引入到classpath中。

比如考虑上传文件,几个关键点就是可以传什么类型的文件?可以传多大的文件?传过来以后放哪儿?叫什么名字?

当文件上传过来的时候是放在一个临时目录里的,我们在Action中持有一个成员属性File,这个File指向的就是服务器存放上传文件的临时目录中的实际文件(临时目录中的文件不会长久保存)

这个是default.properties中默认的一些属性,不配置临时目录的话默认就是用javax.servlet.context.tempdir

# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
struts.multipart.maxSize=2097152

可以在配置文件中使用配置常量,这个配置的常量是全局的,意思就是struts.multipart.saveDir表示所有上传的文件都临时保存在这个目录中,而struts.multipart.maxSize指的是整个项目的上传文件的最大的size不能超过多少。

而下面这个是在action下设置的,针对的是单个的Action级别的:

allowedExtensionsSet 允许的文件类型扩展名,基于扩展名检查并不是特别靠谱

allowedTypesSet 允许的文件类型

maximumSize 允许的文件大小,这个zhide是一次上传的文件大小的上限

二、如何做?

1. 单文件上传:

首先来一个最简单的用法,即一次上传一个文件,参数都使用默认值。

只需要写一个前端:

  <form action="uploadAction" method="post" enctype="multipart/form-data">
<input type="file" name="file"/><br/>
<input type="submit" value="上传" />
</form>

然后定义Action:

 public class UploadAction extends ActionSupport {

     private File file; //与表单file控件的name一致,指向了服务器临时目录中的上传文件
private String fileContentType; //File变量的名+ContentType,表示文件的MIME类型
private String fileFileName; //File变量的名+FileName,表示文件上传之前的名称 @Override
public String execute() throws Exception { System.out.println(file+" "+fileContentType+" "+fileFileName); //do something... return SUCCESS;
} public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} public String getFileContentType() {
return fileContentType;
} public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
} public String getFileFileName() {
return fileFileName;
} public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
} }

Action中的三个变量:

File file : 对于单文件上传类型,这个文件的名字必须是File类型的并且变量的名字要和前端表单的文件控件的name属性一致,会给这个变量赋值指向处于服务器上传文件临时目录中的那个文件。

fileContentType :文件的MIME类型,比如image/jpeg,application/octet-stream之类的。

fileFileName : 文件名,文件在上传之前在客户端的磁盘上存在就必然有一个名字,这里就是那个名字。

总结一下单文件上传:

1.表单的enctype="multipart/form-data"属性。

2.Action的三个成员变量file(文件本身),fileContentType(文件MIME类型),fileFileName(文件名)。

2. 多文件上传

  <form action="uploadAction" method="post" enctype="multipart/form-data">
<input type="file" name="file"/><br/>
<input type="file" name="file"/><br/>
<input type="submit" value="上传" />
</form>

Action:

 public class UploadAction extends ActionSupport {

     private File file[]; // 与表单file控件的name一致,指向了服务器临时目录中的上传文件
private String fileContentType[]; // File变量的名+ContentType,表示文件的MIME类型
private String fileFileName[]; // File变量的名+FileName,表示文件上传之前的名称 @Override
public String execute() throws Exception { for(int i=0;i<file.length;i++){
System.out.println(file[i]+" "+fileContentType[i]+" "+fileFileName[i]);
} // do something... return SUCCESS;
} public File[] getFile() {
return file;
} public void setFile(File[] file) {
this.file = file;
} public String[] getFileContentType() {
return fileContentType;
} public void setFileContentType(String[] fileContentType) {
this.fileContentType = fileContentType;
} public String[] getFileFileName() {
return fileFileName;
} public void setFileFileName(String[] fileFileName) {
this.fileFileName = fileFileName;
} }

或者:

 public class UploadAction extends ActionSupport {

     private List<File> file; // 与表单file控件的name一致,指向了服务器临时目录中的上传文件
private List<String> fileContentType; // File变量的名+ContentType,表示文件的MIME类型
private List<String> fileFileName; // File变量的名+FileName,表示文件上传之前的名称 @Override
public String execute() throws Exception { for (int i = 0; i < file.size(); i++) {
System.out.println(file.get(i) + " " + fileContentType.get(i) + " "
+ fileFileName.get(i));
} // do something... return SUCCESS;
} public List<File> getFile() {
return file;
} public void setFile(List<File> file) {
this.file = file;
} public List<String> getFileContentType() {
return fileContentType;
} public void setFileContentType(List<String> fileContentType) {
this.fileContentType = fileContentType;
} public List<String> getFileFileName() {
return fileFileName;
} public void setFileFileName(List<String> fileFileName) {
this.fileFileName = fileFileName;
} }

多文件上传的要点就是在单文件上传的基础上前端多个名字相同的表单文件域,Action接收的地方改成File[]数组或者List<File>集合都可以。

3. 文件下载

配置文件:

<?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>
<package name="default" namespace="/" extends="struts-default" >
<action name="downloadAction" class="struts_practice_001.DownloadAction">
<!-- 要将结果类型设置为stream -->
<result type="stream">
<!-- inputName跟Action中的输入流的名字要相同 -->
<param name="inputName">file</param>
<!-- contentDisposition的attachment表示让浏览器的默认行为是保存文件,而filename是保存文件的时候的默认名字 -->
<param name="contentDisposition">attachment;filename="psd.jpg"</param>
</result>
</action>
</package>
</struts>

Action:

 public class DownloadAction extends ActionSupport {

     private InputStream file; //将要下载的文件读到这个输入流中

     @Override
public String execute() throws Exception {
file=ServletActionContext.getServletContext().getResourceAsStream("psb.jpg");
return SUCCESS;
} public InputStream getFile() {
return file;
} public void setFile(InputStream file) {
this.file = file;
} }

文件下载的关键点:

1. Action中有一个InputStream,里面是要被下载的文件的流。

2.配置文件中配置一个为stream类型的结果,传入两个参数:inputName跟Action的InputStream名字保持一致,contentDisposition是给浏览器看的提示。

4.配置参数详解

<struts>
<!-- 文件上传到服务器的临时目录 -->
<constant name="struts.multipart.saveDir" value="/tempUpload"></constant>
<!-- 允许的文件最大尺寸(全局) -->
<constant name="struts.multipart.maxSize" value="1024000000"></constant> <package name="default" namespace="/" extends="struts-default" >
<action name="uploadAction" class="struts_practice_001.UploadAction">
<result>/success.jsp</result>
<interceptor-ref name="fileUpload">
<!-- 允许的MIME类型 -->
<param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg</param>
<!-- 允许上传文件的最大尺寸 -->
<param name="maximumSize">1024000</param>
</interceptor-ref>
<!-- 一定要写在后面 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>

这里有一点关于参数上的疑问,就是<constant name="struts.multipart.saveDir" value="/tempUpload" />我这样写的话这个目录究竟保存到了哪里呢?看别的博客上说的是

发现我的也是保存到了E盘上,但是这种说法很没有是根本没有说服力,设想一下如果让我们来设计的话,肯定要优先保存到剩余可用空间最大的分区上啦。

如果路径没有以/开头的话就是保存到user.dir。

参考资料:Struts2中的struts.multipart.saveDir的配置

三、原理是啥?

。。。。好长,以后闲下来再慢慢分析源码吧。。。

(没错,就这么太监了.....我发现写东西是件很奇妙的事情,有的时候连着写好几个小时感觉很爽,有的时候写不到十分钟就感觉头和蛋一起疼明明写不出来还硬要使劲挤牙膏....o(╯□╰)o)

Struts2拦截器之FileUploadInterceptor的更多相关文章

  1. Struts2拦截器之ModelDrivenInterceptor

    叙述套路: 1.这是个啥东西,它是干嘛用的? 2.我知道它能干啥了,那它咋个用呢? 3.它能跑起来了,但是它是咋跑起来的是啥原理呢? 一.ModelDriven是个啥?他能做什么? 从前端页面到后端的 ...

  2. Struts2拦截器之DefaultWorkflowInterceptor

    一.DefaultWorkflowInterceptor是什么 首先说这东西是干嘛来的,在action中可以对传进来的数据进行验证,方法是实现Validateable接口的validate():voi ...

  3. Struts2拦截器之ExceptionMappingInterceptor(异常映射拦截器)

    一.异常拦截器是什么? 异常拦截器的作用是提供一个机会,可以设置在action执行过程中发生异常的时候映射到一个结果字符串而不是直接中断. 将异常整合到业务逻辑中,比如在分层系统的调用中可以从底层抛出 ...

  4. Struts2拦截器的执行过程浅析

    在学习Struts2的过程中对拦截器和动作类的执行过程一度陷入误区,特别读了一下Struts2的源码,将自己的收获分享给正在困惑的童鞋... 开始先上图: 从Struts2的图可以看出当浏览器发出请求 ...

  5. Struts2拦截器总结<转>

    由于项目中在登录跳转到其他应用程序模块的时候有用到拦截器,因此查看了一下相关资料. 原文地址:http://blog.csdn.net/sendfeng/article/details/4248120 ...

  6. Struts2 拦截器具体配置过程

    拦截器差点儿遍布每个程序中,所以贴出拦截器配置的具体过程,希望可以帮到大家. Struts2 拦截器具体配置过程 <interceptors> <!-- 先定义拦截器 --> ...

  7. Struts2拦截器详解

    一.Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的    拦截器对象,然后串成一个列 ...

  8. 转载 - Struts2 拦截器详细配置过程

    出处:http://www.blogjava.net/zzzlyr/archive/2009/10/12/297998.html Struts2 拦截器详细配置过程 1:所有拦截器的超级接口Inter ...

  9. Struts2 拦截器配置以及实现

    @(Java ThirdParty)[Struts|Interceptor] Struts2 拦截器配置以及实现 Struts2的拦截器应用于Action,可以在执行Action的方法之前,之后或者两 ...

随机推荐

  1. 联不上网 Unable to initialize Windows Sockets interface. General failure.

    电脑莫名联不上网 Unable to initialize Windows Sockets interface. General failure. Unable to initialize the W ...

  2. QQ空间个人中心的广告

    http://qzonestyle.gtimg.cn/qzone/space_item/boss_pic/*.jpghttp://img*.paipaiimg.com/*.jpghttp://cn.q ...

  3. BZOJ1212——L语言

    题目大意:每一个字符串都可以分解成一些个单词组成,现在给你一些单词,再给你一个字符串, dp吧,设f[i]为从0开始,到i结束的字符串前缀是否可以被分解,因为单词长度很小,所以,这就T了, (什么逻辑 ...

  4. Unity 用户手册用户指南二维纹理 (Texture 2D)

    http://www.58player.com/blog-2327-953.html 二维纹理 (Texture 2D) 纹理 (Textures) 使您的 网格 (Meshes).粒子 (Parti ...

  5. Android6.0以后动态增加权限

    private void test() throws IOException { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { in ...

  6. Android_bug之 task ':app:mergeDebugResources'. > Some file crunching failed, see logs f

    今天调试安卓程序遇到的问题Error:Execution failed for task ':app:mergeDebugResources'. > Some file crunching fa ...

  7. Apache Thrift 服务开发框架学习记录

    Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架. 前言: 目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Servic ...

  8. 网站标签栏ico设置代码

    放在公共文件的header中 <link rel="Shortcut Icon" href="{APP_PATH}favicon.ico" />

  9. php过滤ascii控制字符

    还记得以前在工作中,将爬来的其它网站的数据导到xml.但是会遇到一个问题:即网页会有ascII的控制字符. 一开始以为是别人为了防止采集而加入的,然后发现一个就往过滤表里加一个.直到慢慢发现,他们都是 ...

  10. http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/

    http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/ box-shadow  :   http://blog.csdn.net/freshlover/a ...