【原创】论struts2上传文件进度条

    最近在做一个文件上传中显示进度条的功能,也在网上搜了下例子还挺多的包括JSP版和SERVLET版的。这几个版本都比较好实现,但是struts2版本的进度条非常少,有个把例子但是也运行不了。但是公司用的又是S2,开始按照JSP版的弄了一个晚上还是无法实现。无奈之下只能睡觉了,睡觉的时候想到了S2文件的上传到action开始执行这一步的时候其实文件已经在服务器上了,action要做的就是将文件复制到目的地址。因此文件上传的所有工作都在S2中的拦截器中完成的。就是FileUploadInterceptor拦截器,由于是封装好了的,因此决定第二天开始研究S2的文件上传源码。

     第二天研究了FileUploadInterceptor拦截器发现该类并不做任何IO的操作,因此文件的上传还不是在该类中处理的,要再往下层研究。最后找出了S2实现的关系图也是S2的核心实现。如下图所示:

 

 

    发现文件的上传工作在类JakartaMultiPartRequest中进行的。只要在该类中做点文章就能够对数据流的监控了。但是问题又来了,如果用一个改过的类替换掉JakartaMultiPartRequest就改动了S2的包了,觉得这样的做法并不方便。应该找到能够在外部进行动态的配置比较好。

     接着我想到了所有的请求都要经过FilterDispatcher这个类,通过这个类匹配不同的拦截器。通过源代码最后找到了ConfigurationManager类,系统是由该类来创建Dispatcher的,它需要xwork.xml配置文件的配置动态的创建Dispatcher。到这里我就想到了S2包下的配置文件,这里有个默认的配置文件:struts-default.xml。系统也会通过这个文件加载一些默认的信息。结果找到了以下的配置:

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true"/>

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true" />

这就意味着可以作较少的改动就能够替换掉JakartaMultiPartRequest类了,只要我写一个实现了MultiPartRequest接口就可以了。

   当然S2的文件上传还要其他的一些外部类,上面只是针对S2的一个切入点。

 

    以及以下的这些包:(demo中加入了DWR框架进行异步通信进度条效果更好)

 

 因此新建一个GarryMultiPartRequest类实现了MultiPartRequest接口;GarryMultiPartRequest类的方法与JakartaMultiPartRequest完全一样只要修改parse()方法即可——添加一个IO流的Listener就可以监听文件上传状态了。如下图:

 

代码清单:

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"%>

<html>

    <head>

        <title>Simple upload page</title>

        <script src='resources/js/upload.js'> </script>

        <script src='<%=request.getContextPath() %>/dwr/interface/UploadMonitor.js'> </script>

        <script src='<%=request.getContextPath() %>/dwr/engine.js'> </script>

        <script src='<%=request.getContextPath() %>/dwr/util.js'> </script>

       

    </head>

    <body>

        <form action="<%=request.getContextPath() %>/fileUpload.action" enctype="multipart/form-data" method="post"

            onsubmit="startProgress()">

            <h1>

                Web upload

            </h1>

            <input class="default" type="file" id="file1" name="excel" />

            <br />

            <input type="submit" value="begin upload" id="uploadbutton" />

 

            <br />

 

            <div id="progressBar" style="display: none;">

 

                <div id="theMeter">

                    <div id="progressBarText"></div>

 

                    <div id="progressBarBox">

                        <div id="progressBarBoxContent"></div>

                    </div>

                </div>

            </div>

        </form>

    </body>

</html>

Dwr.xml

<dwr>

    <allow>

        <create creator="new" javascript="UploadMonitor">

            <param name="class" value="be.telio.mediastore.ui.upload.UploadMonitor"/>

        </create>

        <convert converter="bean" match="be.telio.mediastore.ui.upload.UploadInfo"/>

    </allow>

</dwr>

Web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <display-name>Ajax Upload</display-name>

 

    <filter>

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

       <filter-class>

           org.apache.struts2.dispatcher.FilterDispatcher

       </filter-class>

    </filter>

    <filter-mapping>

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

       <url-pattern>/*</url-pattern>

    </filter-mapping>

 

    <servlet>

       <servlet-name>dwr-invoker</servlet-name>

       <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>

       <init-param>

           <param-name>debug</param-name>

           <param-value>false</param-value>

       </init-param>

       <init-param>

           <param-name>logLevel</param-name>

           <param-value>WARN</param-value>

       </init-param>

    </servlet>

 

    <servlet-mapping>

       <servlet-name>dwr-invoker</servlet-name>

       <url-pattern>/dwr/*</url-pattern>

    </servlet-mapping>

 

    <!-- The Usual Welcome File List -->

    <welcome-file-list>

       <welcome-file>index.jsp</welcome-file>

    </welcome-file-list>

 

</web-app>

 

      最后运行项目的时候还是失败了,系统并没有使用我写的GarryMultiPartRequest类,问题出一定出在了struts-default.xml文件的配置上了。最后发现了一个更加灵活的配置方法,不用更改S2jar包文件。在struts.xml里添加以下的配置:

<constant name="struts.multipart.parser" value="xxx.xxx.GarryMultiPartRequest" />

这样系统才会调用自定义的GarryMultiPartRequest类。

      系统运行后效果如图所示:

 运行一切正常!因此我的思路是对的,也得到一个结论S2action只是辅助的组件,如果要深入的了解S2应该好好看下interceptor包下的类,毕竟S2interceptor为主。

相关源码已经放到了CSDN下载区了

评论 73
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值