选择图片文件(可拖动)并上传功能的实现——js对象

一 . 具体效果

效果

二 .大略实现流程和设计思路

  • 大略流程


    image.png
  • 设计思路
    将整个模块封装到jquery插件中,直接通过调用插件来实现。整个选择图片上传模块有包括三大对象,分别是:
    (a)uploadTools(上传工具): 初始化界面和所有界面上的工具,并为他们绑定相应的uploadEvent事件
    (b)uploadEvent(事件处理): 定义事件处理函数
    (c)uploadFileList(文件处理):处理虚拟的文件列表 fileList(通过fileList就能看到上传前的所有图片信息)

三 . 主要代码

    1. 需要用到的参数
      "uploadId":uploadId,  //初始化整个功能模板的div的id
      "uploadUrl":"#",    //上传地址
      "fileType":"*",     //文件类型
      "fileMaxNum":-1,  //文件最大数量:-1为没有限制 ,必须为整数
      "fileMaxSize":-1, //单个文件最大大小:-1为没有限制, 单位kb
      "canDrag":true,     //文件是否可拖拽
      "isHiddenUploadBtn":false,    //是否隐藏上传按钮  , 默认为不隐藏
      "isHiddenCleanBtn":false,     //是否隐藏清除按钮 , 默认为不隐藏
      "ismultiple":true,            //是否可以多文件上传
      "isAutoClean":true,           //是否上传后自动完成清除
      "fileSavePath":"",            //文件上传后后台设置的根目录
      "uploadSuccess":function(){}, //上传成功后的回调函数
      "uploadFalse":function(){},   //上传失败后的回调函数

2.整个的js代码

//定义一个jquery上传插件
$.fn.extend({
  "initUpload":function(opt){   //传入参数opt对象
    if(typeof opt !=="object"){
      console.log("传入的参数有误");
      return ;
    }
    var uploadId=$(this).attr("id")
    if(uploadId==null||uploadId==""){
      console.log("请传入一个有id的元素");
      return ;
    }
    //将其余默认值赋给opt
    $.each(uploadTools.getInitOption(uploadId),function(key,value){
      if(opt[key]===undefined){
        opt[key]=value;
      }
    })

    uploadTools.flushOpt(opt);        //保存opt
    uploadTools.initWithLayout(opt);  //初始化文件布局
    uploadTools.initWithDrag(opt);    //初始化拖拽事件
    uploadTools.initWithSelectBtn(opt);   //初始化选择文件按钮
    uploadTools.initWithUploadBtn(opt);   //初始化上传按钮
    uploadTools.initWithCleanBtn(opt);    //初始化清除文件按钮
    uploadFileList.initFileList(opt); //初始化已添加文件列表
  }
})

/****************
*上传基本工具和操作
*****************/
var uploadTools={
  /*
  *基本参数配置
  */
  "getInitOption":function(uploadId){
    var initOption={
      "uploadId":uploadId,  //初始化整个功能模板的div的id
      "uploadUrl":"#",    //上传地址
      "fileType":"*",     //文件类型
      "fileMaxNum":-1,  //文件最大数量:-1为没有限制 ,必须为整数
      "fileMaxSize":-1, //单个文件最大大小:-1为没有限制, 单位kb
      "canDrag":true,     //文件是否可拖拽
      "isHiddenUploadBtn":false,    //是否隐藏上传按钮  , 默认为不隐藏
      "isHiddenCleanBtn":false,     //是否隐藏清除按钮 , 默认为不隐藏
      "ismultiple":true,            //是否可以多文件上传
      "isAutoClean":true,           //是否上传后自动完成清除
      "fileSavePath":"",            //文件上传后后台设置的根目录
      "uploadSuccess":function(){}, //上传成功后的回调函数
      "uploadFalse":function(){},   //上传失败后的回调函数
    }

    return initOption;
  },
  /*
  *初始化布局
  */
  "initWithLayout":function(opt){
    console.log(opt)
    var optionId=opt.uploadId;
    //文件和上传,清理按钮模板
    var btnsStr = '';
    btnsStr += '<div class="uploadBtns">';
    btnsStr += '<ul>';
    btnsStr += '<li><div class="selectFileBtn">选择文件</div></li>';
    if(!opt.isHiddenUploadBtn){
      btnsStr += '<li><div class="uploadFileBtn"><i class="iconfont icon-shangchuan"></i></div></li>';
    }
    if(!opt.isHiddenCleanBtn){
      btnsStr += '<li><div class="deleteFileBtn"><i class="iconfont icon-shanchu"></i></div></li>';
    }
    btnsStr += '</ul>';
    btnsStr += '</div>';
    //文件显示框
    var fileStr = '';
    fileStr += '<div class="box">'
    fileStr += '</div>'
    $("#"+optionId).append(btnsStr);
    $("#"+optionId).append(fileStr)
  },
  /*
  * 初始化拖拽事件
  */
  "initWithDrag":function(opt){
    if(opt.canDrag){
      $(document).on({
        //拖进时触发
        dragenter:function(e){
          e.preventDefault();
        },
        //拖来拖去时触发
        dragover:function(e){
          e.preventDefault();
        },
        //放置拖放元素时触发
        drag:function(e){
          e.preventDefault();
        },
        //拖出来时触发
        dragleave:function(e){
          e.preventDefault();
        }
      })
      var box=$("#"+opt.uploadId+" .box");
      if(box.length!==0){
        $(document).on("drop",function(e){
          uploadEvent.dragEvent(e,opt);
        })
      }
    }
  },
  /*
  *初始化选择按钮
  */
  "initWithSelectBtn":function(opt){
    var uploadId=opt.uploadId;
    $("#"+uploadId+" .selectFileBtn").off();
    $("#"+uploadId+" .selectFileBtn").on("click",function(){
      uploadEvent.selectFileEvent(opt);
    })
  },
  /*
  * 初始化上传文件按钮
  */
  "initWithUploadBtn":function(opt){
    var uploadId=opt.uploadId;
    $("#"+uploadId+" .uploadFileBtn i").css("color","#0099ff");
    $("#"+uploadId+" .uploadFileBtn").off();
    $("#"+uploadId+" .uploadFileBtn").on("click",function(){
      uploadEvent.uploadFileEvent(opt);
    })
  },
  /*
  *初始化清除文件按钮
  */
  "initWithCleanBtn":function(opt){
    var uploadId=opt.uploadId;
    $("#"+uploadId+" .deleteFileBtn i").css("color","#0099ff");
    $("#"+uploadId+" .deleteFileBtn").off();
    $("#"+uploadId+" .deleteFileBtn").on("click",function(){
      uploadEvent.cleanFileEvent(opt);
    })
  },

  /*
  *time秒上传进度为100%:隐藏图片上的删除按钮->一点时间后显示图片上传成功icon
  */
  "getFileUploadProgressMsg":function(opt,time){
    var seconds=0;
    if(time!==undefined){
      seconds=time;
    }
    var uploadId=opt.uploadId;
    $("#"+uploadId+" .status i").css("opacity","0")
    var timer=setInterval(function(){
      $("#"+uploadId+" .status i").addClass("icon-right");
      $("#"+uploadId+" .status i").css("opacity","1")
      clearInterval(timer);
      //uploadTools.initWithUploadBtn(opt);
      uploadTools.initWithCleanBtn(opt);    //只恢复清除全部按钮 , 清除后才能初始化上传按钮
    },seconds);
  },
  /*
  * 初始化图片上的删除按钮
  */
  "initWithDeleteBtn":function(opt){
    uploadId=opt.uploadId;
    $("#"+uploadId+" .box i").off();
    $("#"+uploadId+" .box i").on("click",function(){
      var thisFileItem=$(this).parent().parent()
      //修改存储文件列表fileList
      var index=thisFileItem.attr("fileCodeId");
      var fileListArray=uploadFileList.getFileList(opt);
      //fileListArray.splice(index,1);    //不能使用splice,因为连续删除时fileCodeId不变,fileListArray[index]可能会不存在
      delete fileListArray[index]         //delete会使数组长度不变 , 但是被删除的值为undefined
      uploadFileList.setFileList(fileListArray,opt);
      thisFileItem.remove();
    })
  },
  /*
  *禁用文件上传
  */
  "disableUploadBtn":function(opt){
    if(!opt.isHiddenUploadBtn){
      var uploadId=opt.uploadId;
      $("#"+uploadId+" .uploadFileBtn").off();
      $("#"+uploadId+" .uploadFileBtn i").css("color","#DDDDDD");
    }

  },
  /*
  *禁用清除文件按钮
  */
  "disableCleanBtn":function(opt){
    if(!opt.isHiddenCleanBtn){
      var uploadId=opt.uploadId;
      $("#"+uploadId+" .deleteFileBtn").off();
      $("#"+uploadId+" .deleteFileBtn i").css("color","#DDDDDD");
    }
  },
  /*
  *禁用图片上的删除按钮
  */
  "disableDeleteBtn":function(opt){
    var uploadId=opt.uploadId;
      $("#"+uploadId+" .box i").off();
  },
  /*
  * 配合拖动事件的存值操作 setData
  */
  "flushOpt":function(opt){
    var uploadId=opt.uploadId;
    $("#"+uploadId).data("opt",opt)
  },
  /*
  * 添加文件
  ***判断文件是否具有被添加的条件
  */
  "addFileList":function(fileList,opt){
    //判断所有文件个数是否超出opt.fileMaxNum
    var fileListArray=uploadFileList.getFileList(opt)   //暂时的文件存储列表
    var len=0;        //fileListArray还存在的元素的个数(不为undefined)
    for(var i=0;i<uploadFileList.getFileList(opt).length;i++){
      if(uploadFileList.getFileList(opt)[i] !== undefined){
        len++;
      }
    }
    if(fileList.length+len>opt.fileMaxNum){
      alert("最多只能上传"+opt.fileMaxNum+"个文件");
      return;
    }
    for(var i=0;i<fileList.length;i++){
      //判断是不是重复文件
      if(uploadTools.isFileExist(fileList[i],opt)){

        alert("文件''"+fileList[i].name+"''已存在啦");
        continue;
      }
      //判断文件类型是否符合
      var nameArray=fileList[i].name.split(".");
      var thisType=nameArray[nameArray.length-1];
      if(opt.fileType=="*"||uploadTools.isInArray(thisType,opt.fileType)){
        //判断文件大小是否符合
        var maxSize=opt.fileMaxSize*1000;
        if(opt.fileMaxSize==-1||fileList[i].size<=maxSize){
          //添加文件
          var imgUrl="";  //获取文件路径
          if(window.createObjectURL !== undefined){   //base
            imgUrl=window.createObjectURL(fileList[i]);
          }
          else if(window.URL !== undefined){          //mozilla(firefox)
            imgUrl=window.URL.createObjectURL(fileList[i]);
          }
          else if(window.webkitURL !== undefined){    /// webkit or chrome
            imgUrl=window.webkitURL.createObjectURL(fileList[i]);
          }
          var fileId=fileListArray.length;    //用来给每一个文件添加一个独一无二的标志
          var imgstr="";
          imgstr += '<div class="fileItem" fileCodeId="'+fileId+'">';
          imgstr += '<div class="imgShow">';
          imgstr += '<img src="'+imgUrl+'" width="150" height="150" />';
          imgstr += '</div>';
          imgstr += '<div class="status"><i class="iconfont icon-close"></i></div>';
          imgstr += '<div class="fileName">'+fileList[i].name+'</div>';
          imgstr += '</div>';
          $("#"+opt.uploadId+" .box").eq(0).append(imgstr);
          //将通过文件添加进文件列表
          fileListArray[fileListArray.length]=fileList[i];
        }
        else{
          alert("文件过大,请控制在"+opt.fileMaxSize+"kb以内");
          continue;     //上传到文件中只有超过最大容量的
        }
      }
      else{
        var str="不支持该文件上传,支持的文件格式有"
        for(var j=0;j<opt.fileType.length;j++){
          str+= " "+opt.fileType[j];
        }
        alert(str);
        return;
      }
    }
    uploadTools.initWithDeleteBtn(opt);
    uploadFileList.setFileList(fileListArray,opt);
  },

  /*
  *判断某个值是否在数组里
  */
"isInArray":function(str,array){
    for(var i=0;i<array.length;i++){
      if(array[i]==str){
        return true;
      }
    }
    return false;
  },
  /*
  *判断文件是否已存在
  */
  "isFileExist":function(file,opt){
    var fileList=uploadFileList.getFileList(opt);
    for(var i=0;i<fileList.length;i++){
      //当图片全部删除时,会出现fileList[i]=undefined
      if(fileList[i]==undefined){
        continue;
      }
      else if(fileList[i].name==file.name && fileList[i].size==file.size){
        return true;
      }

    }
    return false;
  },


}
/********
上传事件处理
********/
var uploadEvent={
  /*
  *拖动放置时的操作事件
  **判断是否为符合配置参数的的文件
  */
  "dragEvent":function(e,opt){
    e.preventDefault();
    var fileList=e.originalEvent.dataTransfer.files;    //jquery的file要去e.originalEvent里面拿,原生JS可以直接由e.dataTransfer.files获取
    uploadTools.addFileList(fileList,opt);
  },
  /*
  * 按选择文件时触发的事件
  */
  "selectFileEvent":function(opt){
    var uploadId=opt.uploadId;
    //添加一个type=file的按钮
    var str="";
    str+='<input type="file" id="fileSelectInput" class="fileSelectInput" />'
    $("#"+uploadId).append(str);
    if(opt.ismultiple){
      $("#fileSelectInput").attr("multiple","multiple");
    }
    $("#fileSelectInput").on("change",function(e){
      uploadTools.addFileList(this.files,opt);
      $("#fileSelectInput").remove();
    })
    $("#fileSelectInput").click();


  },
  /*
  *清除所有文件: 禁用选择文件按钮->清空文件列表->初始化选择文件
  */
  "cleanFileEvent":function(opt){
    var uploadId=opt.uploadId;
    $("#fileSelectInput").remove(); //移除选择文件按钮
    uploadFileList.setFileList([],opt); //清空文件列表
    $("#"+uploadId+" .box").html("");
    uploadTools.initWithUploadBtn(opt); //初始化上传文件:配合上传后通过清除文件来重新上传
  },
  /*
  * 上传文件事件
  */
  "uploadFileEvent":function(opt){
    uploadTools.flushOpt(opt);  //将opt的数据存储起来
    //判断是否有上传前的回调函数
    //..
    var fileList=uploadFileList.getFileList(opt);
    var formData=new FormData();    //记录要发送的数据
    var fileNum=0;    //记录被上传的文件次数,如果为0则提醒
    for(var i=0;i<fileList.length;i++){
      if(fileList[i]!==undefined){
        formData.append("file",fileList[i]);
        fileNum++;
      }
    }
    if(fileNum==0){
      alert("没有文件可以上传");
      return;
    }
    formData.append("fileSavePath",opt.fileSavePath);
    uploadTools.disableUploadBtn(opt);  //禁用上传按钮
    uploadTools.disableCleanBtn(opt);   //禁用清除按钮
    uploadTools.disableDeleteBtn(opt);  //禁用图片上的删除按钮
    //设置了上传文件存储地址则使用AJAX上传 , 否则模拟上传
    if(opt.fileSavePath==""||opt.fileSavePath=="#"){
      //模拟上传:隐藏图片上的删除按钮->一点时间后显示图片上传成功icon
      uploadTools.getFileUploadProgressMsg(opt,2000);
    }
    else{
      //使用AJAX上传
      $.ajax({
        type:"post",
        url:opt.uploadUrl,
        data:formData,
        procssData:false,   //data不转化为字符串
        contentType:false,  //避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。
        success:function(data){
          uploadTools.getFileUploadProgressMsg(opt);
          if(opt.isAutoClean){
            uploadEvent.cleanFileEvent();
          }

        },
        error:function(e){
          alert("上传文件失败");
        }
      })
    }
  },

}

/***********
*上传文件处理
***********/
var uploadFileList={
  /*初始化存储已添加文件的列表*/
  "initFileList":function(opt){
    opt.fileList=new Array();
  },
  /*获取已添加文件的列表*/
  "getFileList":function(opt){
    return opt.fileList;
  },
  /*向列表添加文件*/
  "setFileList":function(fileList,opt){
    opt.fileList=fileList;
    //nowFileList=preFileList.concat(fileList);
    uploadTools.flushOpt(opt)
  }
}

四. 具体的流程图和完整的代码下载链接

https://download.csdn.net/download/qq_36828433/10904749

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容

  • 路过珠江大桥 红尘滚滚 碧水滔滔 一桥乡愁,一水痴恋 他大声呼喊着她的名字 北风吹来 往事如烟 多少落花流水去 在...
    蝴蝶恋她阅读 208评论 12 28
  • 引言 我们重视用户的隐私。您在使用我们的服务时,我们可能会收集和使用您的相关信息。我们希望通过本《隐私政策》向您说...
    强_3cba阅读 438评论 0 1
  • 痴德阅读 391评论 0 0