内容属原创,转载请注明出处
项目中需要用到一个多附件上传的控件,找了一圈没找到中意的(唯一一个中意点的还不开源,费用比较高),这不,只得自己抡刀上了。
需求是什么
这么个上传的东东,要做哪些事情呢?
必须要干的事情:
1. 不能太丑,可以很素。
原生的input file实在和项目主体不太搭配,需要另外想办法。
2. 需要支持上传多个附件,比如后台有个字段叫做 影像资料,这个影像资料,也许就是一张正面照,也许,还有一堆的证件照,需要支持多个。
3. 需要一个页面上支持多个这样的控件,今天有个影像资料,明天可能就出来一个 资质证书,这不,就得俩了。
4. 需要能查列表,上传、下载、删除
最好有的内容:
5. 实时进度条
6. 图片类型的附件可以预览。
7. 可以限制上传的附件类型。
8. 支持配置上传单个或者多个
上面这些东西,一个一个来呗。
怎么开工
做这么个东东,至少要涉及到两块内容:
1. 前端展示
2. 后端处理
既然咱项目用了spring,用了jquery,那么,就从这两玩意入手呗,于是,决定这样干:
1. 前端自定义一个jquery插件
2. 后台基于springMVC和commons-fileupload-1.2.1.jar实现上传的具体业务
闲话莫提,开始捉刀。
前端插件的那些事
jquery是个好东东,要搞个插件有非常具体的套路,直接往上面套就好了,关键在于,逻辑怎么实现?
以前的项目用的是flash的插件,如今既然不想再依赖flash,那么,就用form提交来搞吧,步骤变成了这样子的:
1. 初始化时调用后台query接口,生成列表,列表上支持下载和删除。
2. 初始化时生成一个类型为 file的input,并绑定一个change事件 callback
3. 在callback中,动态生成一个form和一个iframe,并且把原来的file移到新的form中,另外再生成一个file放到原来的位置。把该form扔到队列
4. 如果当前没有提交的任务存在,那么生成一个提交的任务。
提交的任务中又在干嘛呢?
主要有下面几个事情要做:
1. 当前有没有正在提交还没提交成功的form?如果有,继续下面的步骤,如果没有,从队列中拿一个未提交的form,提交,如果队列空了,任务结束。
2. 当前提交的form的目的地(iframe)的内容有没有发生改变(通过检测某个具体的dom)?如果发生了改变,说明提交已经结束,进入结束的处理。如果没发生改变,那么,取进度条吧。
2.1 提交已经结束,看下,成功还是失败?成功了,设置进度条,生成删除按钮,再从第一个步骤开始。失败了,提示下上传失败。
2.2 提交还未结束,调用接口取下进度吧,同时,过个500毫秒从第一个步骤开始再来一次。
嗯,前端所有的逻辑基本上都在这里了。
后端的那些事
既然用了commons-fileupload-1.2.1.jar,那么只要做如下事情:
1. 新增类UploadProgressListener实现ProgressListener接口,在该接口的实现类中,首先从url里根据规则解析出来uploadId参数,然后往session例如该uploadId对应的进度。
session里存的是个map,key为uploadId,value为进度值。
2. 继承 CommonsMultipartResolver 实现一个类xx.xx.xx.CommonsMultipartResolver,在该实现类中通过类似下面代码注入进度条监听:
String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); ProgressListener pListener = new UploadProgressListener(request); fileUpload.setProgressListener(pListener);