创建 Js图片上传实现方法总结

图片上传是前端开发过程最常碰见的功能之一。现在有很多成熟的图片上传插件uploadify、file upload、 webuploader 等,除了这些HMTL5技术上也支持了这一需求,今天我们就来聊一聊这些是怎么实现的。以及根据他的原理自己写一个上传的功能。

一、uploadify插件

uploadify是一款免费的jquery的上传插件,有flash版本和html5版本,html5版本支持鼠标拖拽上传,因为一些HTML5版的一些兼容性,以flash版本使用居多,所以下面介绍flash版本的实现

     1)html代码





   
  

     2)JS代码

$(function(){
    $("#file_upload").uploadify({
        'auto':true,        //是否为自动上传
        'swf':'/uploadify/uploadify.swf',     //上传的flash插件
        'uploader':'/uploadify/uploadify.php',     //后台处理上传文件的脚本
        'buttonImage' :'/uploadify/browser.btn.png',      //上传按钮的外观为自定义图片
        'buttonText':'上传图片',      //上传按钮的文字信息
        'debug':true,       //开启uploadify的调试模式
        'fileObjName':'myFile',      //服务器端接收的对象,如$_POST['myFile']
        'fileSizeLimit':'5MB',      //上传文件的最大值
        'fileTypeDesc':'支持的格式:',                                   //可选择文件类型说明 
        'fileTypeExts':'*.jpg;*.png;*.bmp;*.gif',     //允许的文件扩展名
        'formData':{'somekey':'somevalue','someotherkey':1},  //上传文件时上传需要的表单值
        'height':'50px',                                                                      //按钮的高度
        'width':'100px',                                                                     //按钮的宽度
        'method':'post',                                                                    //上传的方式,默认为post
        'multi':true,                                                                           //允许批量上传,默认为true
        'preventCaching':true,                                                       //是否阻止缓存
        'progressData':'percentage',                                            //上传队列显示为速度还是百分比
        'onDialogOpen':function(){ alert('ok');}                           //打开上传按钮浏览框时触发事件
        'onUploadStart':function(){ }                                             //文件开始上传时触发事件
        'onUploadSuccess':function(file,data,response){        //文件上传成功时触发事件
        //成功以后这里继续操作
        },
                                                                                
      'onFallback':function(){                                                      //检测FLASH失败调用    
             alert("请安装FLASH控件后再试。");    
      },  
      //正在上传。。  
        'onSelect': function(file){  
           $("#alertDiv").text("正在上传...");  
            $("#alertDiv").show();  
        }, 
        'onSelectError':function(file, errorCode, errorMsg){    
            switch(errorCode) {    
               case -100:    
                  alert("上传的文件数量已经超出系统限制的"+$('#file_upload').uploadify('settings','queueSizeLimit')+"个文件!");    
                   break;    
               case -110:    
                   alert("文件 ["+file.name+"] 大小超出系统限制的"+$('#file_upload').uploadify('settings','fileSizeLimit')+"大小!");    
                          break;    
               case -120:    
                   alert("文件 ["+file.name+"] 大小异常!");    
                   break;    
               case -130:    
                   alert("文件 ["+file.name+"] 类型不正确!");    
                   break;    
            }    
        },  
        //所有文件处理完成时
        'onQueueComplete': function(queueData){ 
            alert(queueData.uploadsSuccessful);  
        }   


    });
});

   3)PHP后代的代码

public function uploadify(){
    if(!empty($_FILES){
        import('ORG.Net.UploadFile');
        $name = time().rand();
        $upload = new UploadFile();
        $upload->maxSize = 3145728;
        $upload->allowExts = array('jpg','gif','png','jpeg');
        $upload->savePath = './Public/upload/';
        $upload->saveRule = $name;
        if(!$upload->upload()){
            echo $upload->getErrorMsg();
        }else{
            $info = $upload->getUploadFileInfo();
            echo $info[0]['svaename'];
        }
    }
}
    

  uploadify插件分HTML5版本和FLAS版本,在chorme等为了安全性考试的浏览器中访问时直接flash被屏弊掉,而在firfox等浏览器如果不默认安装flash,则该功能不能实现,所以我体验不太好。如果研用HTML5版的一些低版本不支持

二、jquery file upload插件 

     1)基本使用

      jQuery File Upload主要使用了XHR作为上传方式,并且利用了相当多的现代浏览器功能,所以可以实现诸如批量上传、超大文件上传、图片预览、拖拽上传、上传进度显示、跨域上传等功能。

     Query File Upload包含了一堆文件,最核心的部分必须包括以下文件:

       1.jQuery核心库                         建议使用jQuery 1.8以上版本
       2.jquery.ui.widget.js :           jQuery UI Widget
       3.jquery.iframe-transport.js : 扩展iframe数据传输
       4.jquery.fileupload.js :          jQuery File Upload核心类
       5. jquery.xdr-transport.js         在IE下应载入此文件解决跨域问题

      引入文件以后html如下:

       


       js代码如下:      

       $('#fileupload').fileupload();

    2)一些扩展

          这就完成了一个简单的上传设置。只不过这只是一个最简单的使用方式,它完全实现一些扩展如下:

         上传完成以后的操作:

$('#fileupload').fileupload({
  done: function (e, data) {
         //do something
  }
});       
        
        进度条的设置

$('#fileupload').fileupload('option', {
   progressall: function (e, data) {
       var progress = parseInt(data.loaded / data.total * 100, 10);
       console.log(progress + '%');
   }
});

       更多扩展可以查看官方网站API

  3)一些注意的坑  

     json数据传送响应

     由于采用XHR在传递数据,服务器端返回的通常是JSON格式的响应,但是IE会将这些JSON响应误认为是文件传输,然后直接弹出下载框询问是否需要下载。

      解决方法:

      是必须将相应的Http Head从 Content-Type: application/json更改为 Content-Type: text/plain 

        定制自己的UI困难

        因为官方特意给了一个UI上的设置,这里的东西不可局部更改,更改时导致UI混乱。因此得他细找出来功能点进行指定的UI覆盖才可以,具体细节这里不在详细讲述了 

三、webuploader插件

      webUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件,使用WebUploader还可以批量上传文件、支持缩略图等等众多参数选项可设置,以及多个事件方法可调用,你可以随心所欲的定制你要的上传组件。

     1)html代码




   
   webuploader
   
   
   
   


 
   

   
选择图片




     2)js代码

 

     3)php代码

     public function webuploader() {
   $upload = new \Think\Upload();                                 // 实例化上传类
   $upload->maxSize   =  3145728 ;                              // 设置附件上传大小
   $upload->exts      =  array('jpg', 'gif', 'png', 'jpeg');    // 设置附件上传类型
   $upload->rootPath  =  './Public/Uploads/';                // 设置附件上传根目录
   $upload->savePath  =  '';                                             // 设置附件上传(子)目录
   $upload->autoSub =    false;                                      // 关闭子目录
   // 上传文件
   $info   =   $upload->upload();
     if(!$info) {                                                                        // 上传错误提示错误信息
              $this->error($upload->getError());
   }else{                                                                                // 上传成功 获取上传文件信息
            $pathArr = array();
             foreach($info as $file){
                    array_push($pathArr, "Public/Uploads/".$file['savepath'].$file['savename']);
           }
            echo json_encode($pathArr);
   }
}

    webUploader是html5和flash两者做了兼容,对高低版本都做了一些良好的支持,而且官网API写的详细,实例很多,容易实用。在这么多插件中主动推荐使用这个插件

四、HMTL5怎么实现

这里提到了html5所以你懂的,这个不要考虑PC端了。一般都是手机端实现图片上传才会用HMTL5实现,具体实现方法如下:

        实现HMTL5图片上传肯定要用到FileReader来读取本地文件,FileReade的属性和方法如下:

属性,所有属性都是只读的:
FileReader.error,读取文件时,出现的DOMError。
FileReader.readyState,读取状态;0,没有数据加载;1,数据正在加载;2,读取已经完成。
FileReader.result,文件内容;该属性只在读取操作完成后才有效,并且格式取决于读取时使用的方法。
事件:
FileReader.onabort,读取操作中止。
FileReader.onerror,读取出现错误。
FileReader.onload,读取成功完成后。
FileReader.onloadstart,读取开始。
FileReader.onloadend,读取完成,无论是否读取成功。
FileReader.onprogress,当读取Blob内容时。
方法:
FileReader.abort() 中止读取。然后readyState变为2。
FileReader.readAsArrayBuffer() 将文件读取成ArrayBuffer。
FileReader.readAsBinaryString() 读取成二进制字符串。
FileReader.readAsDataURL() 读取成DataURL。
FileReader.readAsText() 读取成文本。

 预览功能实现:





图片上传预览



   
   

   


 预览功能实现:

function upload() {
   var xhr = new XMLHttpRequest();
   var progress = document.getElementById("progress")
   progress.style.display = "block";


   xhr.upload.addEventListener("progress", function(e) {
       if (e.lengthComputable) {
           var percentage = Math.round((e.loaded * 100) / e.total);
           progress.value = percentage;
       }
   }, false);


   xhr.upload.addEventListener("load", function(e){
         console.log("上传结束...")
     }, false);


   xhr.open("POST", "upload");
   xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
   xhr.onreadystatechange = function() {
       if (xhr.readyState == 4 && xhr.status == 200) {
           alert(xhr.responseText); // handle response.
           progress.style.display = "none";
           progress.value = 0;
       }
   };
   var file = document.getElementById("imgFile");
   var fd = new FormData();
   fd.append(file.files[0].name, file.files[0]);
   xhr.send(fd);
}

  

五、分析下原理自已动手写一个

上面我们基本总结了图片上传的经常用的插件及HTML5实现的方式。每个都有优点和缺点,一般为了兼容低版本都是走的flash,一旦走的是flash就会出现安装插件的请求,这个体验不好,在一上次做需求的时候需要用到多图片上传,索性自己写了个。

      实现原理:

      通过Iframe+form的结合。设置input file enctype="multipart/form-data" target="ajaxUpload" 属性允许选择多张图片上传,模拟input file上传功能安钮,当input file change的时候 通过form action把当前的图片上传给后台,后台设置,当前端iframe加载完成时获取server端返回的生成服务器上的img URL。解析数据生成远程的img.程现到页面上出来。然后做删除滚动一系列的后续工作等。

      Html代码:




   

           

           
               

                   
                   
                   正在上传...
                   
               

           

       


     JS代码:

var ShensuFn=function(remote){

     this.attr= {
    '_shenText'   : $('._shenText'),    
    '_shenSelect' : $('._shenSelect'),
    '_shenfile'   : $('#fileName'),
    '_shenMsg'    : $('#returnMsg'),
    '_sheniframe' : $('#iframebox'),
    '_shenBox'    : $('.scrollBox'),
    '_shenUrl'    : $('.scrollBox ul'),
    '_shenDaText' : $('#data_text')
     };

   /*上传图片相关逻辑*/
imgUpload:function(){
//当选择当前文件时提交
var lName;
var that=this;
this.attr._shenfile.on('change',function(){
//没有选择图片时
var filVal  = $(this).val();

if(filVal==''){
return;
}
// 提示信息
   that.attr._shenMsg.show();  

   $("#fileForm").submit();
   that.attr._shenfile.val('');
})
//提交加载完成Iframe时设置图片


  this.attr._sheniframe.on('load',function(){
       //取出iframe中的数据
       var body = $(window.frames['ajaxUpload'].document.body); 
       var aLiLeng = that.attr._shenUrl.children().not("#shen-from").length;
       that.attr._shenDaText.text(body.context.textContent);  
       var _data=JSON.parse(that.attr._shenDaText.text());
var res=_data.data;

//如果数据为空或者不存在
   if((!res && _data.error!='-1') || (res.length<1 && _data.error!='-1')){                   
  return;  
  }
  //有错误信息时提示
  if(_data.error=='-1'){   
  alert(_data.errormsg);
  }
  //图片总数量超过9张时
  if((aLiLeng+res.length)>9){
  alert('你上传的图片张数过多,已为您添加前9张图片')
  //删除多余图片数
  res.splice(9-aLiLeng); 
  $("#fileForm").hide();
  //图片总数量等于9张时
  }else if((aLiLeng+res.length)==9){
  $("#fileForm").hide();
  }
  //隐藏数据
  that.attr._shenDaText.hide();
  //生成img
  for(var i=0;i 
  $("

  • ").insertBefore($('#shen-from')); 
     
      var aLiLeng = that.attr._shenUrl.children().not("#shen-from").length;
      //UL的宽度
      that.attr._shenUrl.css('width',((aLiLeng+1)*(118+15))+'px');  
     
      //UL的scrollLeft
    aLiLeng>2?(that.attr._shenBox.scrollLeft((aLiLeng-2)*(118+15))):(that.attr._shenBox.scrollLeft(0));

      //loading隐藏
      that.attr._shenMsg.hide();

      //关闭当前的图片并删除
      that.attr._shenUrl.find('.close-btn').click(function(){
    $(this).parent().remove();
    var aLiLeng = that.attr._shenUrl.children().not("#shen-from").length; 
    //删除后计算UL的宽度
      that.attr._shenUrl.css('width',((aLiLeng+1)*(118+15))+'px');
      //删除后计算UL的left
    aLiLeng>2?that.attr._shenBox.scrollLeft((aLiLeng-2)*(118+15)):that.attr._shenBox.scrollLeft(0);
    //删除时检测当前的图片个数控制是否显示上传安钮 
       
      if(aLiLeng<9){
     
      $("#fileForm").show();
      }
      });
     
    })
     }

     new ShensuFn();

    总结:如上所述,总结所有目前图片上传的方法。及自己手动写的方式等,其中插件推荐使用webUploader,做了HMTL5 和FLASH的兼容处理。下面手动写的iframe的方式也是一种很好的实现方法,用它实现了局部刷新的功能。因为iframe加载整个页面不会刷新,而且避免再次出现了flash这个东西让用户安装的不好的体验方式,唯一要求的就是后台的一些配合,不过做开发需要后台的配合这个也合乎常理。



    你可能感兴趣的:(原生JS)