zoukankan      html  css  js  c++  java
  • 新鲜出炉的jquery fileupload 插件

    内容属原创,转载请注明出处

    为什么做这个东东

    项目中需要用到一个多附件上传的控件,找了一圈没找到中意的(唯一一个中意点的还不开源,费用比较高),这不,只得自己抡刀上了。

    需求是什么

    这么个上传的东东,要做哪些事情呢?

    必须要干的事情:

    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);
    View Code

    3. 在spring的配置文件中配置multipartResolver为上面步骤中新实现的类: 

    <bean id="multipartResolver" class="xx.xx.xx.CommonsMultipartResolver" p:defaultEncoding="UTF-8" >

    嗯,差不多就这样了。只是,这里面有个比较大的坑

    在 UploadProgressListener 这个类中拿到的request的parameter一直是空的。。要等这个步骤做完之后request的参数才有值,这样,支持多个附件上传的那个参数uploadId怎么样都拿不到。。最后,幸好MVC支持在url里带参数,于是上传的url就变成了:

      @RequestMapping(value="/file/{uploadId}/upload.json")

    这样,可以通过规则在request中拿到getRequestURI()之后再解析出来uploadId的值

    差不多可以收工了。

    写在题外的

    用的时候,还要注意什么下面这么些东西:

    1. 后台存储附件需要这么张关系表,里面保存了 file_group_id,file_id,file_name,file_path,file_size 至少这么些数据。

    2. 控件基于jquery 1.7.2,未测试其他版本

    3. 配置控件 上传、新增、删除、下载以及获取进度条的action时,注意需要相对工程的根目录配置,前面不要带 /
    4. 控件的action需要返回json数据,需要注意如下内容:
      a. 新增返回的json为如下格式,至少需要返回fileId和fileGroupId字段:
      

    {model_list:[{"file_group_id":"XXXXX","file_id":"XXXXXXX"}]}

      同时,注意返回时,需要设置返回数据的头部信息为 HTML,java中为:

      

    response.setContentType("text/html;charset=UTF-8");

    b. 删除时后台通过参数 file_id 接收要删除的 文件编号,不抛异常则认为是删除成功

    c. 下载时后台通过参数 file_id 接收要下载的文件编号,返回文件流
    d. 获取文件列表时,后台通过url里的参数 fileGroupId查询该组号下的所有附件,的返回json数据为:

    {model_list:[{file_group_id:'XX',file_id:'XXX1',file_name:'XX文件',file_path:'test/test/XX文件_20140810010101.html',file_size:1001},{file_group_id:'XX',file_id:'XXX2',file_name:'XX文件',file_path:'test/test/XX文件_20140810010102.html',file_size:1001}]}

    e. 获取文件上传进度,返回的格式为json格式:

    {"percent":10}

    注意,为了支持多个文件上传读取进度,每一个文件上传时有一个唯一的 uploadId,获取文件上传进度需要根据该参数进行,提交时的参数名为 upload_id

    下载

    这个fileupload的前端插件的地址已经放在github上,路径:

    https://github.com/kevin82008/fileupload

    效果图:

    水平所限,如有不对,欢迎拍砖。

    ------------------------------------

    当天空没有颜色的时候,就用自己的双手画出绚烂的彩虹。程序员的天空,永远都是多彩多姿的。

  • 相关阅读:
    angularjs的$on、$emit、$broadcast
    angularjs中的路由介绍详解 ui-route(转)
    ionic入门教程-ionic路由详解(state、route、resolve)(转)
    Cocos Creator 加载使用protobuf第三方库,因为加载顺序报错
    Cocos Creator 计时器错误 cc.Scheduler: Illegal target which doesn't have uuid or instanceId.
    Cocos Creator 构造函数传参警告 Can not instantiate CCClass 'Test' with arguments.
    Cocos Creator 对象池NodePool
    Cocos Creator 坐标系 (convertToWorldSpaceAR、convertToNodeSpaceAR)
    Cocos Creator 常驻节点addPersistRootNode
    Cocos Creator 配合Tiled地图的使用
  • 原文地址:https://www.cnblogs.com/kevinYX/p/3903173.html
Copyright © 2011-2022 走看看