在做B/S系统时,通常会涉及到上传文件和下载文件,在没接struts2框架之前,我们都是使用apache下面的commons子项目的FileUpload组件来进行文件的上传,但是那样做的话,代码看起来比较繁琐,而且不灵活,在学习了struts2后,struts2为文件上传下载提供了更好的实现机制,在这里我分别就单文件上传和多文件上传的源代码进行一下讲解,这里需要导入文件下载上传的两个jar文件,一个是commons-fileupload-1.2.2.jar,另一个是commons-io-2.0.1.jar

struts2单文件上传:

首先是一个jsp文件上传页面,这个比较简单,就是一个表单,里面有个文件上传框

   <!--在进行文件上传时,表单提交方式一定要是post的方式,因为文件上传时二进制文件可能会很大,还有就是enctype属性,这个属性一定要写成multipart/form-data,
  不然就会以二进制文本上传到服务器端-->
  <form action="fileUpload.action" method="post" enctype="multipart/form-data">
  
username: <input type="text" name="username"><br>
file: <input type="file" name="file"><br> <input type="submit" value="submit">
</form>

原理是就是struts2的FileUploadInterceptor拦截器过滤。

接下来是FileUploadAction部分代码,因为struts2对上传和下载都提供了很好的实习机制,所以在action这段我们只需要写很少的代码就行:

Action中文件属性的命名规则约定,在struts2内部的的FileUploadInterceptor.class完成的

String[] fileName = multiWrapper.getFileNames(inputName);//得到请求的所有文件名

if (isNonEmpty(fileName)) { 
                    // get a File object for the uploaded File 
                    File[] files = multiWrapper.getFiles(inputName); 
                    if (files != null && files.length > 0) { 
                        List<File> acceptedFiles = new ArrayList<File>(files.length); 
                        List<String> acceptedContentTypes = new ArrayList<String>(files.length); 
                        List<String> acceptedFileNames = new ArrayList<String>(files.length); 
                        String contentTypeName = inputName + "ContentType";//默认就是input名称+ContentType 
                        String fileNameName = inputName + "FileName";//默认就是input名称+FileName

for (int index = 0; index < files.length; index++) { 
                            if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) { 
                                acceptedFiles.add(files[index]); 
                                acceptedContentTypes.add(contentType[index]); 
                                acceptedFileNames.add(fileName[index]); 
                            } 
                        }

if (!acceptedFiles.isEmpty()) { 
                            Map<String, Object> params = ac.getParameters();//添加到parameters中 这样就可以通过OGNL注入到action了

params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()])); 
                            params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()])); 
                            params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()])); 
                        } 
                    }

public class FileUploadAction extends ActionSupport
{
private String username;

   //注意,file并不是指前端jsp上传过来的文件本身,而是文件上传过来存放在临时文件夹下面的文件,还有就是file变量的命名是和对应jsp的name属性值一样的。
private File file; //提交过来的file的名字
private String fileFileName; //提交过来的file的MIME类型
private String fileContentType; public String getUsername()
{
return username;
} public void setUsername(String username)
{
this.username = username;
} public File getFile()
{
return file;
} public void setFile(File file)
{
this.file = file;
} public String getFileFileName()
{
return fileFileName;
} public void setFileFileName(String fileFileName)
{
this.fileFileName = fileFileName;
} public String getFileContentType()
{
return fileContentType;
} public void setFileContentType(String fileContentType)
{
this.fileContentType = fileContentType;
} @Override
public String execute() throws Exception
{
String root = ServletActionContext.getServletContext().getRealPath("/upload"); InputStream is = new FileInputStream(file); OutputStream os = new FileOutputStream(new File(root, fileFileName));
//也可以这么写
       //String root = ServletActionContext.getServletContext().getRealPath("/upload"+fileFileName); 
//OutputStream os = new FileOutputStream(root);
System.out.println("fileFileName: " + fileFileName);

    // 因为file是存放在临时文件夹的文件,我们可以将其文件名和文件路径打印出来,看和之前的fileFileName是否相同
System.out.println("file: " + file.getName());
System.out.println("file: " + file.getPath()); byte[] buffer = new byte[500];
int length = 0; while(-1 != (length = is.read(buffer, 0, buffer.length)))
{
os.write(buffer);
} os.close();
is.close(); return SUCCESS;
}
}

自己写的例子:

<form action="upload" method="post" enctype="multipart/form-data">

     <input  type="file" name="file" value="文件上传"><br>

     <input  type="submit" value="提交">
</form>

  


package action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import javax.servlet.ServletContext;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport {

/**
*
*/
private static final long serialVersionUID = 1L;
private File file;
private String fileContentType;
private String fileFileName;

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;
}

@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("file:"+file);
System.out.println("fileContentType:"+fileContentType);
System.out.println("fileFileName:"+fileFileName);

ServletContext ctx=ServletActionContext.getServletContext();
/*String dir=ctx.getRealPath("/files/"+fileFileName);
new File(dir).getParentFile().mkdir();
FileOutputStream out=new FileOutputStream(dir);*/
String dir=ctx.getRealPath("/files");
new File(dir).mkdir();
FileOutputStream out=new FileOutputStream(dir+"/"+fileFileName);
System.out.println(dir+"/"+fileFileName);
FileInputStream in=new FileInputStream(file);
byte[] buffer=new byte[1024];
int len=0;
while((len=in.read(buffer))!=-1){
out.write(buffer,0,len);
}
out.close();
in.close();

return super.execute();
}

}

  

首先我们要清楚一点,这里的file并不是真正指代jsp上传过来的文件,当文件上传过来时,struts2首先会寻找struts.multipart.saveDir(这个是在default.properties里面有)这个name所指定的存放位置,我们可以新建一个struts.properties属性文件来指定这个临时文件存放位置,如果没有指定,那么文件会存放在tomcat的apache-tomcat-7.0.29\work\Catalina\localhost\目录下,然后我们可以指定文件上传后的存放位置,通过输出流将其写到流里面就行了,这时我们就可以在文件夹里看到我们上传的文件了。

文件上传后我们还需要将其下载下来,其实struts2的文件下载原理很简单,就是定义一个输入流,然后将文件写到输入流里面就行,关键配置还是在struts.xml这个配置文件里配置:

FileDownloadAction代码如下:

public class FileDownloadAction extends ActionSupport
{
public InputStream getDownloadFile()
{
return ServletActionContext.getServletContext().getResourceAsStream("upload/通讯录2012年9月4日.xls");
} @Override
public String execute() throws Exception
{
return SUCCESS;
}
}

我们看,这个action只是定义了一个输入流,然后为其提供getter方法就行,接下来我们看看struts.xml的配置文件:

        <action name="fileDownload" class="com.xiaoluo.struts2.FileDownloadAction">
<result name="success" type="stream">
<param name="contentDisposition">attachment;filename="通讯录2012年9月4日.xls"</param>
<param name="inputName">downloadFile</param>
</result>
</action>

struts.xml配置文件有几个地方我们要注意,首先是result的类型,以前我们定义一个action,result那里我们基本上都不写type属性,因为其默认是请求转发(dispatcher)的方式,除了这个属性一般还有redirect(重定向)等这些值,在这里因为我们用的是文件下载,所以type一定要定义成stream类型,告诉action这是文件下载的result,result元素里面一般还有param子元素,这个是用来设定文件下载时的参数,inputName这个属性就是得到action中的文件输入流,名字一定要和action中的输入流属性名字相同,然后就是contentDisposition属性,这个属性一般用来指定我们希望通过怎么样的方式来处理下载的文件,如果值是attachment,则会弹出一个下载框,让用户选择是否下载,如果不设定这个值,那么浏览器会首先查看自己能否打开下载的文件,如果能,就会直接打开所下载的文件,(这当然不是我们所需要的),另外一个值就是filename这个就是文件在下载时所提示的文件下载名字。在配置完这些信息后,我们就能过实现文件的下载功能了。

struts2多文件上传:

其实多文件上传和单文件上传原理一样,单文件上传过去的是单一的File,多文件上传过去的就是一个List<File>集合或者是一个File[]数组,首先我们来看一下前端jsp部分的代码,这里我用到了jquery来实现动态的添加文件下载框以及动态的删除下载框:

    <script type="text/javascript" src="script/jquery-1.8.1.js"></script>
<script type="text/javascript"> $(function()
{
$("#button").click(function()
{
var html = $("<input type='file' name='file'>");
var button = $("<input type='button' name='button' value='删除'><br>"); $("#body div").append(html).append(button); button.click(function()
{
html.remove();
button.remove();
})
})
}) </script>
</head> <body id="body"> <form action="fileUpload2.action" method="post" enctype="multipart/form-data"> username: <input type="text" name="username"><br>
file: <input type="file" name="file">
<input type="button" value="添加" id="button"><br>
<div></div>
<input type="submit" value="submit"> </form> </body>

file的名字必须都命名成file才行,然后处理多文件上传的action代码如下:

public class FileUploadAction2 extends ActionSupport
{
private String username;

  //这里用List来存放上传过来的文件,file同样指的是临时文件夹中的临时文件,而不是真正上传过来的文件
private List<File> file;

  //这个List存放的是文件的名字,和List<File>中的文件相对应
private List<String> fileFileName; private List<String> fileContentType; public String getUsername()
{
return username;
} public void setUsername(String username)
{
this.username = username;
} public List<File> getFile()
{
return file;
} public void setFile(List<File> file)
{
this.file = file;
} public List<String> getFileFileName()
{
return fileFileName;
} public void setFileFileName(List<String> fileFileName)
{
this.fileFileName = fileFileName;
} public List<String> getFileContentType()
{
return fileContentType;
} public void setFileContentType(List<String> fileContentType)
{
this.fileContentType = fileContentType;
} @Override
public String execute() throws Exception
{
String root = ServletActionContext.getServletContext().getRealPath("/upload"); for(int i = 0; i < file.size(); i++)
{
InputStream is = new FileInputStream(file.get(i)); OutputStream os = new FileOutputStream(new File(root, fileFileName.get(i))); byte[] buffer = new byte[500]; @SuppressWarnings("unused")
int length = 0; while(-1 != (length = is.read(buffer, 0, buffer.length)))
{
os.write(buffer);
} os.close();
is.close();
} return SUCCESS;
}
}

这样同样将其写到一个输出流里面,这样我们就可以在文件夹里看到上传的多个文件了

接下来的文件下载就和刚才的文件下载一模一样,struts.xml也是一样的,这里就不再重复了

总结:总的来说,struts2提供的文件上传下载机制简化了我们很多代码,我们可以在以后的项目中使用该机制,同样我们也可以使用FileUpload组件来进行文件的上传,这个都是因个人爱好决定!

struts2的文件上传的更多相关文章

  1. jsp\struts1.2\struts2 中文件上传(转)

    jsp\struts1.2\struts2 中文件上传 a.在jsp中简单利用Commons-fileupload组件实现 b.在struts1.2中实现c.在sturts2中实现现在把Code与大家 ...

  2. Struts2+Uploadify文件上传使用详解

    Uploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示.不过官方提供的实例是php版本的,本文将详细介绍Uploadify在java中的使用,您也可以点击下面的链接进行演示或下 ...

  3. Struts2 多文件上传

    Struts2多文件上传只需要将 单文件上传中的File变成File[]  即可,上篇文章:单文件上传 <form action="${pageContext.request.cont ...

  4. Struts2图片文件上传,判断图片格式和图片大小

    1. 配置Struts2能够上传的最大文件大小 使用Struts2进行文件上传的时候,Struts2默认文件大小最大为2MB,如果要传大一点的文件,就需要修改struts.xml配置文件,重新设置能够 ...

  5. Struts2实现文件上传下载功能(批量上传)

    今天来发布一个使用Struts2上传下载的项目, struts2为文件上传下载提供了好的实现机制, 首先,可以先看一下我的项目截图 关于需要使用的jar包,需要用到commons-fileupload ...

  6. Struts2实现文件上传(四)

    Struts2实现文件上传 配置文件struts.xml <!-- /* * $Id: struts.xml 1364077 2012-07-21 12:57:02Z lukaszlenart ...

  7. Struts2实现文件上传(三)

    Struts2实现文件上传 配置文件web.xml <?xml version="1.0" encoding="UTF-8"?> <web-a ...

  8. Struts2实现文件上传(二)

    Struts2实现文件上传 文件上传页面 file.jsp: <%@ page language="java" import="java.util.*" ...

  9. Struts2实现文件上传(一)

    Struts2实现文件上传 文件上传成功后结果页面 result.jsp: <%@ page language="java" import="java.util.* ...

随机推荐

  1. Weblogic页面应用查询oracle数据库后台报错或页面日期格式显示错误

    问题:在生产环境中有两台WEB服务器,分别为227和228,部署的应用代码都是每日同步的,两边完全一致,但是某些页面查询数据时,227无结果,并且后台报java数组越界的错误,而228一切正常.经开发 ...

  2. 数组中第K小的数字(Google面试题)

    http://ac.jobdu.com/problem.php?pid=1534 题目1534:数组中第K小的数字 时间限制:2 秒 内存限制:128 兆 特殊判题:否 提交:1120 解决:208 ...

  3. truncate table和delete table 的区别

    truncate table和不带 where 的 detele 功能一样,都是删除表中的所有数据. 但TRUNCATE TABLE 速度更快,占用的日志更少,这是因为 TRUNCATE TABLE ...

  4. jmeter性能测试小小的实战

    项目描述: 被测网站:xqtesting.blog.51cto.com 指标:响应时间以及错误率 场景: 新建 一个线程组,设置线程属性: 线程数为10 Ramp-Up-Penod(in second ...

  5. Mac下安装 PIL

     最近入手MacBook Pro 在配置PIL环境的时候遇到一些问题.现在把解决方式记录下来,希望对有需要的有所帮助. 1. 安装brew : brew 又叫Homebrew,是Mac OSX上的软件 ...

  6. 一步一步了解Cocos2dx 3.0 正式版本开发环境搭建(Win32/Android)

    cocos2d-x 3.0发布有一段时间了,作为一个初学者,我一直觉得cocos2d-x很坑.每个比较大的版本变动,都会有不一样的项目创建方式,每次的跨度都挺大…… 但是凭心而论,3.0RC版本开始 ...

  7. Linux操作系统下搭建LAMP环境

    准备:先在目录home/csy/下建website代码目录,然后新建php文件,命名为test.php. 在test.php编写代码如下: <? php phpinfo(); ?> 保存并 ...

  8. RPC 框架通信原理

    RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据: ...

  9. 掷骰子-IOS新手项目练习(抱歉,由于个人原因,图片没显示,要源码的项目私聊)

    ---恢复内容开始--- 今天我们来讲的就是项目<掷骰子> 首先我们先下载资源包,也就是我们需要的图片[点击图片下载] 在我们下载完图片之后,我们就可以开始创建项目 一.我们项目的做法可以 ...

  10. DIOCP之编写第一个应用程序(二)

    构建client界面: 构建界面要比写代码更难爱,不是专业UI设计太丑,先有个界面,好写代码,客户端代码与界面设计思想:界面与数据之间分离处理,不能要接收数据的地方写代码,不然以后修改程序会死人的.