李顺利
随笔-50  评论-170  文章-0  trackbacks-0

Struts2下多文件的上传与下载

目录

关键词... 1

写在前面... 1

需求... 1

环境... 2

目录结构... 3

重要文件的看点... 3

web.xml. 3

struts.xml. 4

UploadAction. 5

DownloadAction. 8

UploadConfigurationRead. 10

工程结果截图... 13

提供原代码下载... 14

 

关键词

多文件 上传 下载 随意文件 java Struts2 单例 配置 动态读取 李顺利 

 

写在前面

    在网络上,对于Java处理文件上传和下载的技术比较多,而Struts作为一款优秀的框架也提供了非常方便的文件上传和下载,而网上的一些例程都非常的不全面,概括来:

1)   文件上传比较多,多文件上传少一点

2)   文件下载很少的,看似简单,实则不然

3)   文件下载一般都是单文件或者固定的文件,并没有(很少)实现随意文件的下载的例子

最近也在研究一下文件的上传和下载,在整合网上、浪曦风中叶老师和自己的学习的思想,写了这个工程,提供给大家参考,所以的代码终在IEFireFoxChrome测试通过。

 

需求

1.能够对多个文件进行上传(可以选择上传文件个数,也即上传文件个数不定)

2.能够对上传路径进行配置文件(upload.properties)指定,使用了一些类似单例模式的静态代码块

3.对配置文件中的路径可以进行动态读取(不重启服务器)

4.Struts2进行下载处理,能对上传的所有文件进行下载(多个)

5.文件保存的名称UUID生成,不过显示并下载的名称都是原文件名称

(人性化,通过UploadFiles处理)

 

环境

最新的Struts2struts-2.1.8MyEclipseTomcatIEFireFoxChrome

 

目录结构

clip_image001

 

重要文件的看点

web.xml

    <filter>

        <filter-name>struts2</filter-name>

        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

    </filter>

    web.xml中使用了最新的Struts2的中央处理器类org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter,而不再是以前的org.apache.struts2.dispatcher.FilterDispatcherFilterDispatcher在新版本Struts2中已经标注为过时了,请大家尽量使用最新的filter

 

struts.xml

<?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.i18n.encoding" value="utf8" />

    <package name="file" namespace="/" extends="struts-default">

       <action name="showUpload">

           <result>/upload.jsp</result>

       </action>

       <action name="upload" class="org.usc.file.UploadAction">

           <result name="input">/upload.jsp</result>

<!--          <result name="success">/upload_success.jsp</result>-->

           <result name="success">/download.jsp</result>

           <interceptor-ref name="fileUpload">

<!--大家可以设置成自己的配置,想文件类型和大小等限制          -->

<!--              <param name="maximumSize">2097152</param>单位是字节   2M  2097152B       -->

<!--              <param name="allowedTypes">image/bmp,image/x-png,image/png,image/gif,image/jpeg,image/jpg,image/pjpeg</param>-->

<!--              -->

<!--                 容许文件类型为doc,ppt,xls,pdf,txt,java-->

<!--              -->

           </interceptor-ref>

           <interceptor-ref name="defaultStack"></interceptor-ref>

       </action>

 

       <action name="download" class="org.usc.file.DownloadAction">

           <result name="success" type="stream">

              <param name="contentDisposition">attachment;filename="${fileName}"</param>

              <param name="inputName">downloadFile</param>

           </result>

       </action>

    </package>

</struts>

 

就是文件上传和下载的一些Struts2配置,注意上传的时候,请引入

<interceptor-ref name="defaultStack"></interceptor-ref>

下载的配置中注意:<param name="inputName">downloadFile</param>

其他的配置解释网上很多,不懂的可以先google学习一下。

 

UploadAction

在此文件中请注意文件数组的使用,因为是多文件

 

package org.usc.file;

import java.io.File;

import java.util.ArrayList;

import java.util.List;

import java.util.UUID;

import org.apache.commons.io.FileUtils;

import org.apache.struts2.ServletActionContext;

import org.usc.utils.UploadConfigurationRead;

import com.opensymphony.xwork2.ActionSupport;

 

/**

 * 多文件上传类

 *

 * @author MZ

 *

 * @Time 2009-11-24下午09:26:44

 */

public class UploadAction extends ActionSupport

{

 

    /**

     *

     */

    private static final long serialVersionUID = 1L;

    private File[] upload;// 实际上传文件

    private String[] uploadContentType; // 文件的内容类型

    private String[] uploadFileName; // 上传文件名

    private List<UploadFiles> uploadFiles = new ArrayList<UploadFiles>();

 

    public String execute() throws Exception

    {

       try

       {

           String targetDirectory = ServletActionContext.getServletContext()

                  .getRealPath("/"+ UploadConfigurationRead.getInstance().getConfigItem("uploadFilePath").trim());// 获得路径

           for (int i = 0; i < upload.length; i++)

           {

              String fileName = uploadFileName[i];// 上传的文件名

              String type = uploadContentType[i];// 文件类型

              String realName = UUID.randomUUID().toString()+ getExt(fileName);// 保存的文件名称,使用UUID+后缀进行保存

 

              File target = new File(targetDirectory, realName);

              FileUtils.copyFile(upload[i], target);// 上传至服务器的目录,一般都这样操作,

                                                 // 在把路径写入数据库即可

 

              UploadFiles uf = new UploadFiles();// 创建文件

              uf.setUploadContentType(type);

              uf.setUploadFileName(fileName);

              uf.setUploadRealName(realName);

 

              uploadFiles.add(uf);// 添加到需要下载文件的List集合中

 

          

           }

           ServletActionContext.getRequest().setAttribute("uploadFiles",

                  uploadFiles);

 

       } catch (Exception e)

       {

           e.printStackTrace();

           addActionError(e.getMessage());

 

           return INPUT;

       }

 

       return SUCCESS;

 

    }

 

    public File[] getUpload()

    {

       return upload;

    }

 

    public void setUpload(File[] upload)

    {

       this.upload = upload;

    }

 

    public String[] getUploadContentType()

    {

       return uploadContentType;

    }

 

    public void setUploadContentType(String[] uploadContentType)

    {

       this.uploadContentType = uploadContentType;

    }

 

    public String[] getUploadFileName()

    {

       return uploadFileName;

    }

 

    public void setUploadFileName(String[] uploadFileName)

    {

       this.uploadFileName = uploadFileName;

    }

 

    public static String getExt(String fileName)

    {

       return fileName.substring(fileName.lastIndexOf("."));

    }

 

}

 

 

 

DownloadAction

在此文件中要注意public InputStream getDownloadFile()的名称在Struts2配置文件配置,返回的是一个InputStream类型的对象。

 

package org.usc.file;

 

import java.io.InputStream;

import java.io.UnsupportedEncodingException;

import com.opensymphony.xwork2.ActionSupport;

import org.apache.struts2.ServletActionContext;

import org.usc.utils.UploadConfigurationRead;

 

public class DownloadAction extends ActionSupport

{

    private static final long serialVersionUID = 6329383258366253255L;

    private String fileName;

    private String fileRealName;

    public void setFileName()

    {

       // 得到请求下载的文件名

       String fname = ServletActionContext.getRequest().getParameter("name");

       String frealname = ServletActionContext.getRequest().getParameter("realname");

       try

       {

           /*

            * fname参数进行UTF-8解码,注意:实际进行UTF-8解码时会使用本地编码,本机为GBK

            * 这里使用request.setCharacterEncoding解码无效.

            * 只有解码了getDownloadFile()方法才能在下载目录下正确找到请求的文件

            */

           fname = new String(fname.getBytes("ISO-8859-1"), "UTF-8");

           frealname= new String(frealname.getBytes("ISO-8859-1"), "UTF-8");

       } catch (Exception e)

       {

           e.printStackTrace();

       }

       this.fileName = fname;

       this.fileRealName = frealname;

//     System.out.println(fileName);

//     System.out.println(fileRealName);

    }

 

    /*

     * @getFileName 此方法对应的是struts.xml文件中的: <param

     * name="contentDisposition">attachment;filename="${fileName}"</param>

     * 这个属性设置的是下载工具下载文件时显示的文件名, 要想正确的显示中文文件名,我们需要对fileName再次编码

     * 否则中文名文件将出现乱码,或无法下载的情况

     */

    public String getFileName() throws UnsupportedEncodingException

    {

 

       fileRealName = new String(fileRealName.getBytes(), "ISO-8859-1");

 

       return fileRealName;

    }

 

    /*

     * @getDownloadFile 此方法对应的是struts.xml文件中的: <param

     * name="inputName">downloadFile</param> 返回下载文件的流,可以参看struts2的源码

     */

    public InputStream getDownloadFile()

    {

 

       this.setFileName();

       return ServletActionContext.getServletContext().getResourceAsStream("/"+UploadConfigurationRead.getInstance().getConfigItem("uploadFilePath").trim()+"/" + fileName);

    }

 

    @Override

    public String execute() throws Exception

    {

       return SUCCESS;

    }

}

UploadConfigurationRead

动态读取配置文件,借鉴网上的代码

 

package org.usc.utils;

import java.io.File;

import java.io.FileInputStream;

import java.net.URI;

import java.net.URISyntaxException;

import java.util.Properties;

/**

 * 动态读取配置文件类

 *

 * @author MZ

 *

 * @Time 2009-11-24下午08:25:22

 */

public class UploadConfigurationRead {

 

    /**

     * 属性文件全名,需要的时候请重新配置PFILE

     */

    private static String PFILE = "upload.properties";

 

    /**

     * 配置文件路径

     */

    private URI uri = null;

 

    /**

     * 属性文件所对应的属性对象变量

     */

    private long m_lastModifiedTime = 0;

 

    /**

     * 对应于属性文件的文件对象变量

     */

    private File m_file = null;

 

    /**

     * 属性文件所对应的属性对象变量

     */

    private Properties m_props = null;

 

    /**

     * 唯一实例

     */

    private static UploadConfigurationRead m_instance = new UploadConfigurationRead();

 

    /**

     * 私有构造函数

     *

     * @throws URISyntaxException

     */

    private UploadConfigurationRead() {

       try {

           m_lastModifiedTime = getFile().lastModified();

           if (m_lastModifiedTime == 0) {

              System.err.println(PFILE + "file does not exist!");

           }

           m_props = new Properties();

           m_props.load(new FileInputStream(getFile()));

 

       } catch (URISyntaxException e) {

           System.err.println(PFILE+"文件路径不正确");

           e.printStackTrace();

       } catch (Exception e) {

           System.err.println(PFILE+"文件读取异常");

           e.printStackTrace();

       }

    }

 

    /**

     * 查找ClassPath路径获取文件

     *

     * @return File对象

     * @throws URISyntaxException

     */

 

    private File getFile() throws URISyntaxException {

       URI fileUri = this.getClass().getClassLoader().getResource(PFILE).toURI();

       m_file = new File(fileUri);

       return m_file;

    }

 

    /**

     * 静态工厂方法

     *

     * @return 返回ConfigurationRead的单一实例

     */

    public synchronized static UploadConfigurationRead getInstance() {

       return m_instance;

    }

 

    /**

     * 读取一特定的属性项

     */

    public String getConfigItem(String name, String defaultVal) {

       long newTime = m_file.lastModified();

       // 检查属性文件是否被修改

       if (newTime == 0) {

           // 属性文件不存在

           if (m_lastModifiedTime == 0) {

              System.err.println(PFILE + " file does not exist!");

           } else {

              System.err.println(PFILE + " file was deleted!!");

           }

           return defaultVal;

       } else if (newTime > m_lastModifiedTime) {

           m_props.clear();

           try {

              m_props.load(new FileInputStream(getFile()));

           } catch (Exception e) {

              System.err.println("文件重新读取异常");

              e.printStackTrace();

           }

       }

       m_lastModifiedTime = newTime;

       String val = m_props.getProperty(name);

       if (val == null) {

           return defaultVal;

       } else {

           return val;

       }

    }

 

    /**

     * 读取一特定的属性项

     *

     * @param name

     *            属性项的项名

     * @return 属性项的值(如此项存在), 空(如此项不存在)

     */

    public String getConfigItem(String name) {

       return getConfigItem(name, "");

    }

 

}

 

 

工程结果截图

IE(遨游)中多文件上传

clip_image003

IE(遨游)中多文件下载

clip_image005

Firefox中多文件上传

clip_image007

Firefox中多文件下载

clip_image009

Chrome中多文件上传

clip_image011

Chrome中多文件下载

clip_image013

服务器中所以文件

clip_image015

提供原代码下载

FileUpLoadAndDownLoad 
multi-files-upload-and-download(maven)

为了有更好得兼容性,这个小demo已经移植到用maven构建(有些网页反映在eclipse里面部署失败),你可以下载上面的标记为maven的源码,或者通过

svn checkout 
http://usc.googlecode.com/svn/trunk/multi-files-upload-and-download/  
or

git clone git://github.com/lishunli/multi-files-upload-and-download.git
or
fork 
https://github.com/lishunli/multi-files-upload-and-download
后,自己进行maven install并部署
 

如果你已经看到这儿了,那就请再欣赏 使用Struts2上传图片存取到Mysql中并读取出来显示在页面上 另一篇有点类似的博客吧,谢谢。

实际上,这个还可以进行扩展,可以存取上传的文件名和路径到数据库中,再在UI(jsp)上面根据需求进行显示文件,并提供下载,仅抛下砖头了,其它的...如果有什么建议或意见可以通过Q:506817493 Eleeshunli<at>qq.com,大家一起交流。

 

顺利写于2009年1124
最后更新于2013年4月12日



博客中的一些下载已经放到了百度云了,请根据需要下载。【点我去百度云下载】

最后弱弱地说一下,如果可以的话,转载请提供出处( ),谢谢。
posted on 2010-01-07 21:21 李顺利 阅读(27132) 评论(38)  编辑  收藏

评论:
# re: Struts2下多文件的上传与下载 2010-01-08 12:34 | 凡客诚品雪地靴
路过踩踩!  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2010-01-12 10:53 | herry
哇,用的WIN7啊  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2010-09-19 11:30 | 椅子
谢谢!  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-08-15 10:45 | 别当我是菜鸟
太牛了,我认你做师傅吧  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-08-15 20:33 | 李顺利
@别当我是菜鸟
不敢当,实际上现在回头想想,这个写的又不是很好,没有在优化了。谢谢支持。
  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-09-22 17:32 | 搞IT的
扩展到电子作业上去   回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-09-26 15:26 | 李永生
# re: Struts2下多文件的上传与下载 2011-09-26 15:26 | 李永生
我qq497234690  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-09-26 15:30 | 李顺利
@李永生
不好意思,具体的错误信息,不清楚,如果可以的话,可以通过email(leeshunli@qq.com),发送错误的log给我,我看看。  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2011-11-10 13:47 | 小飞
提供的下载很慢、如果楼主有时间的话给我879306004@qq.com邮箱发一份、先谢谢了。  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-11-10 21:06 | 李顺利
@小飞
已经发送了,请查收  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2011-11-11 12:52 | tianyake
不错,挺好!!  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-02-01 23:04 | 陈辉
Struts Problem Report

Struts has detected an unhandled exception:
Messages:
The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
File: org/apache/jasper/compiler/DefaultErrorHandler.java
Line number: 56

这个是什么错误啊  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-02-01 23:05 | 陈辉
能给我解答吗?谢谢喽哦!!!  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-03-18 22:05 | 李顺利
@陈辉
换个 tomcat 或者看看 jstl 包正确否,试试,还不行,google吧。  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2012-03-21 10:12 | haha
jsp在那  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2012-03-21 10:17 | haha
什么呀 一点都不全  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-03-21 12:25 | 李顺利
@haha
请你认真看下好不,不要随便就评论说不全,难道你和别人不同,很多网友都说很不错。
什么jsp在哪儿,什么不全,你难道没看到有下载了。说实话,鄙视你这样的人。  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2012-08-28 12:09 | jun
FileUtils.copyFile(upload[i], target);// 上传至服务器的目录,一般都这样操作,// 在把路径写入数据库即可

该怎么上传文件的信息到数据库啊  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-08-28 12:13 | 李顺利
@jun
博文中已经给出
如果你已经看到这儿了,那就请再欣赏 使用Struts2上传图片存取到Mysql中并读取出来显示在页面上 另一篇有点类似的博客吧,谢谢。

http://www.blogjava.net/lishunli/archive/2010/11/14/338012.html

原理类似  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2012-08-28 13:32 | jun
谢谢您,其实我已经看到了连接并看了那个博客,你的那个是hibernate 写的,而且这两个也有很大的差异,能不能针对这个提供一点思路,其实我只是想把file 的相关信息获取下然后插入到数据库(oracle)就ok ,如果要用您的这个框架我不知道该怎么做,所以想请您提供一点思路。 只需要将file 的相关信息插入即可,并不需要真的将file 上传至库  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-08-28 13:34 | 李顺利
@jun
首先file的相关信息读取应该不难吧(比如大小,文件名,扩展什么的),后面不就是插入数据库的问题了,这个不需要我提示吧,基础的东西。  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2012-08-28 13:54 | jun
其实我就是纠结在信息的获取和封装到插入的对象这里  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-09-19 23:19 | SSA
SDSDSADFDS  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2012-09-19 23:24 | SSA
DD  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2013-03-15 17:00 | 小六
谢谢  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2013-04-03 19:20 | 段鹏
@李顺利

duanps@163.com,发给我一份吧,共同学习。多谢
  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2013-05-03 15:19 | 仰望星空
顶一个,求源码。qq:504773103  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2013-05-03 16:14 | 李顺利
@仰望星空
请认真阅读文章,明明后面有下载有源码还...  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2013-05-03 16:51 | 仰望星空
可是怎么点击之后连接不到服务器呢?  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2013-07-27 17:04 | 雪城无月
写的很好,支持一下,虽然在我自己的机子上用起来有点问题  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2013-08-15 17:15 | 漫步
怎么下载不了源码?  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2013-08-15 18:40 | 李顺利
@漫步
下载不了可以试试svn checkout 或者git clone  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2014-03-20 15:20 | 微笑的小小向日葵
UploadFiles这个类里面都有些什么属性啊?  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2014-03-20 15:21 | 微笑的小小向日葵
我知道了,谢谢你啊!  回复  更多评论
  
# re: Struts2下多文件的上传与下载[未登录] 2014-12-24 16:40 | liu
你好,链接下载不了,能不能发一份源码到email(249788069@qq.com)里,谢谢。  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2015-12-23 15:20 | 桔梗
@liu同求 可以发我一份吗 邮箱1490301228@qq.com 谢谢
  回复  更多评论
  
# re: Struts2下多文件的上传与下载 2015-12-23 15:21 | 桔梗
@liu同求 可以发我一份吗 邮箱1490391228@qq.com 谢谢 正确邮箱  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: