`
richard_2010
  • 浏览: 63483 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

基于SpringMVC文件上传服务器端进度条实现

阅读更多

        文件上传应该大部分人都接触过,一般都是基于commons-fileupload组件来实现,SpringMVC的文件上传功能也是在commons-fileupload组件提供的功能上面做了一些包装功能,使文件上传开发更容易方便。
        首先来看看我们系统对于文件上传功能提出来的需求:
1、能同时上传多个文件;
2、单个文件大小不超过2G;
3、要有进度条可以实时显示上传进度;
4、可以取消正在上传的文件;
5、文件上传到分布式存储系统,保证上传的效率。

        一、实现普通文件上传
        我们知道,类DispatcherServlet是SpringMVC的入口,在其doDispatch方法里面,我们可以看到它会先去检查有没配置multipartResolver 

        如果有的话会先执行它的resolveMultipart方法:

        因此,我们在配置文件中添加:
                则可使用SpringMVC自带的CommonsMultipartResolver实现多个文件上传的功能。

        二、实现进度条
        现在实现带进度条的文件上传一般都是在客户端用flash上传组件计算,或者是通过客户端插件的方式。前者上传组件有大小的限制,后者对于我们系统来说实现过于复杂,开发难度稍大。因此我们采用服务器端计算文件上传进度,客户端轮询的方式。
        Commons-fileupload组件自带了文件上传进度的监听器,类FileUploadBase提供了它的set方法:        

        ProgressListener是一个接口,我们需要自己实现它的update方法,参数pBytesRead表示已经上传到服务器的字节数,pContentLength表示所有文件的总大小,pItems表示第几个文件:

        SpringMVC没有实现监听器,所以如果要监听的话得自己扩展CommonsMultipartResolver类,在newFileUpload里面加入代码设置自己实现的监听器:

        ServletFileUploadExt是对ServletFileUpload类进行的扩展,后面会提到。这样在文件上传的过程中,监听器将得到通知已上传的字节数:


        三、上传到分布式存储系统
        通过阅读commons-fileupload的源码我们知道实际文件上传发生在FileUploadBase类parseRequest(RequestContext ctx)方法里面:

 

        因此我们可以通过继承ServletFileUpload(该类继承自FileUpload)类重写parseRequest方法来实现我们自己的存储方式。这里有个地方需要注意的,一般文件保存到分布式存储系统中,为了减少IO次数,需要实现本地的buffer,等buffer满了后再上传上去:

         但是因为commons-fileupload组件本身有个buffer,而且buffer大小为4096:

 

        因此按照上面实现的话不管自己定义多大的buffer,一次IO传上去的实际不到4096字节(减去http头信息等),我们需要用扩展了BufferedInputStream的类包装下:

        BufferedInputStreamExt主要对read方法做了一些修改:

        去掉了BufferedInputStream类该方法的几条语句,因为在上传组件自带buffer的情况下,读一次后input.available()会为0,此处会导致提前返回而不能把自定义的buffer读满:


        四、取消文件上传
        取消文件上传实现方式为上传时保存上传输入流的引用,取消时关闭流,让输入流产生IO异常或者数组越界异常,同时捕获这些异常,则可取消文件上传。

        五、总结&改进
        由于SpringMVC上传的时候并不能得到单个文件的大小,配置文件限制的大小也是所有文件的大小,非单个文件大小,监听的也是整体文件上传的进度。所以在客户端可以做一些改进,比如模拟一次可以上传多个文件,但实际上传时只上传单个文件,等第一个文件上传完毕后再依次发请求上传第二第三个文件。

 

        欢迎对本文提出的实现方式进行讨论和指导,如有更好的实现方式,亦欢迎指教,谢谢!

 

  • 大小: 13.1 KB
  • 大小: 19.4 KB
  • 大小: 8.8 KB
  • 大小: 7 KB
  • 大小: 15.5 KB
  • 大小: 10 KB
  • 大小: 10.5 KB
  • 大小: 5.8 KB
  • 大小: 25.1 KB
  • 大小: 8.1 KB
  • 大小: 5.2 KB
  • 大小: 4.8 KB
  • 大小: 3.2 KB
  • 大小: 16.7 KB
  • 大小: 4.3 KB
分享到:
评论
2 楼 yijiang_0212 2012-12-10  
有没有源码? 发给我一份,邮箱是yijiang_021219@sina.com
1 楼 wang91wang 2012-08-13  
有没有详细一点的呀

相关推荐

Global site tag (gtag.js) - Google Analytics