兼容IE低版本的文件上傳解決方案

文件上傳兼容簡直頭疼,爲此特地封裝了個方法,支持IE低版本(>=7)上傳及現代瀏覽器顯示上傳進度,css

此方法只是個hello world,jser可根據本身的需求增減功能及樣式html

敬上代碼,拋磚引玉android

調用web

    var $file = $('input控件');
    var config = {
    fileExtension: 'jpg, png, pdf, psd',  //容許上傳de文件格式
    fileSize: 100*1024*1024, //容許上傳的最大尺寸
    uploadUrl: '***', //上傳地址
    deleteUrl: '***', //刪除地址
    uploadCb: function(res){
      console.log('success')
    },
    deleteCb: function(res){
      console.log('delete')
    }
  }
    $file.uploadFile(config)

方法ajax

(function($){
  // 全局變量
  var $this = '', //上傳控件
      $container, //最外層容器
      $showFileContainer, //顯示文件容器
      $showFileItem //顯示單個文件
  var fileId = new Date().getTime(); //時間戳,區分每次上傳
  var config = {};  // 配置參數
  // 關於上傳進度變量
  var ot = 0; //上次調用的時間
  var oloaded = 0; //已上傳文件大小
  var xhr = '';

  $.fn.uploadFile = function(conf){
    // 接收配置參數
    config = conf;
    $this = $(this);
    new initLayout($this)
    var inputData = [];
    /**
     * 上傳文件
     * -----------
     * input files屬性ie10及如下不支持
     * formdata ie10如下不支持
     * 根據是否支持files屬性判斷現代瀏覽器
     */
    $('body').on('change propertychange',$this,function(){
      fileId = new Date().getTime(); //更新時間戳
      // 區分ie10及如下
      if(browserInfo().browser.name == "Internet Explorer" && browserInfo().browser.edition*1 < 11){
        // ie低版本瀏覽器

        // ie單個文件過濾限制
        ie_singleFilefilter()
      }else{
        // 現代瀏覽器
        var files = $this[0].files;
        // files無數據跳出
        if(!files.length){
          return false
        }
        // 單個文件過濾限制
        new singleFilefilter(files)
        return false
      }
      // 最後執行
      clearFile();
    })

    // 刪除單個文件
    $container.on('click',".f-itemDel",function(ev){
      if(!config.deleteUrl){
        return false
      }
      $.ajax({
        type: "POST",
        url: config.deleteUrl,
        data: {},
          success :function(data){
              var $del = $(ev.target);
              $del.closest('.f-item-info').remove();
              // 刪除回調
              config.deleteCb(data);

              clearFile();
          },
          error: function(data){
            
          }
      });
    })
  }


  // 初始化佈局
  function initLayout(){
    var inpId = $this.prop('id')?$this.prop('id'): (new Date).valueOf();
    var $creatParent = $('<div class="f-container">\
    <div class="f-input"></div>\
    <div class="f-preview"></div>\
    <div class="f-button"><label class="f-label-btn" for="'+inpId+'">add file</label></div>\
    <div class="f-showInfo"></div>\
    </div>');
    $this.after($creatParent);
    $creatParent.find('.f-label-btn').append($this);

    $container = $creatParent;
    $showFileContainer = $container.find(".f-showInfo")
  }

  /**
   * singleFilefilter 
   * 單個文件過濾-限制格式、大小、數量
   * -------
   * @param singleFile 
   * 接收單個文件
   * ---------
   * @return
   */
  function singleFilefilter(files){
    var singleFile = files[0]; //獲取單個文件
    var extensions = config.fileExtension.split(','); //容許拓展名
    var singleExtension = '' ;// 單文件拓展名
    var singleSize = singleFile.size; //單文件大小
    var isNext = false;
    // 格式限制
    singleExtension = singleFile.name.substring(singleFile.name.lastIndexOf(".")+1).toLowerCase();
    if(extensions && extensions.length){
      for(var i = 0; i < extensions.length; i++){
        if(singleExtension == extensions[i].trim()){
          isNext = true;
        }
      }
    }
    // 判斷isNext和singleExtension,爲空或爲false時提示
    if(!isNext){
      alert('文件格式不正確!');
      clearFile()
      return false;
    }
    // 大小限制
    if(singleSize > config.fileSize){
      alert("文件過大!")
      clearFile()
      return false;
    }

    //顯示正在上傳文件
    new showFile(singleFile)
    // 獲取數據
    var uploadDate = new FormData();
    uploadDate.append("file",singleFile);
    // ajax上傳
    new ajaxUpload(uploadDate);
  }

  // 現代瀏覽器上傳
  function ajaxUpload (uploadDate){
    $.support.cors = true;
    ot = new Date().getTime();//獲取上傳開始時間
    $.ajax({
      type: "POST",
      url: config.uploadUrl,
      data: uploadDate,//這裏上傳的數據使用了formData 對象
      processData : false,
      //必須false纔會自動加上正確的Content-Type
      contentType : false ,

      //這裏咱們先拿到jQuery產生的 XMLHttpRequest對象,爲其增長 progress 事件綁定,而後再返回交給ajax使用
      xhr: function(){
          xhr = $.ajaxSettings.xhr();
          var res = 0;
          xhr.upload.onprogress=progressFunc; //文件上傳進度
          // 如下部分待測試
          // xhr.upload.onload = res = uploadComplete; //請求完成
          // xhr.upload.onerror =  uploadFailed; //請求失敗
          // xhr.upload.onabort=abortFunc(); //文件上傳取消
            return xhr;
        },
        success :function(data){
          if(config.callback){
            config.callback(data);
          }

          clearFile();
        },
        error: function(data){
        }
    });
  }

  // 文件上傳進度
  function progressFunc(evt){
    // evt.total是須要傳輸的總字節,evt.loaded是已經傳輸的字節。若是evt.lengthComputable不爲真,則evt.total等於0
    var nt = new Date().getTime();//獲取上傳開始時間
    if (evt.lengthComputable) {
      var num = Math.round(evt.loaded / evt.total * 100); //轉換百分比
      if(num == 100){
          // 隱藏進度條
          // hiddenUploading($progressBar);
      }
      num += "%";
      $showFileItem.find(".f-itemPmgressBar .f-pmgress").css({
        width: num
      })

      // 計算速率oloaded
      var preTime = (nt-ot)/1000;
      var preLoad = evt.loaded - oloaded;
      oloaded = evt.loaded; //從新賦值已上傳文件大小,用如下次計算
      var speed = preLoad/preTime;
      var unit = 'b'
        // 單位轉換
      if(speed/1024 > 1){
        speed = speed/1024;
        unit = 'kb';
      }
      if(speed/1024 > 1){
        speed = speed/1024;
        unit = 'M';
      }
      // 小數只保留兩位
      if(parseInt(speed)!=speed){
        speed = speed.toFixed(2);
      }
      // 顯示速度
      $showFileItem.find(".f-itemSpeed").html(speed + unit + "/s" )
      
      // 上傳完刪除進度條及速度
      if(evt.total == evt.loaded){
        $showFileItem.find(".f-itemPmgressBar").remove();
        $showFileItem.find(".f-itemSpeed").remove();
      }
    }
  }

  // 顯示文件數據
  function showFile(file){
    var size = file.size;
    var unit = 'b';
    
    // 單位轉換
    if(size/1024 > 1){
      size = size/1024;
      unit = 'kb';
    }
    if(size/1024 > 1){
      size = size/1024;
      unit = 'M';
    }
    // 小數只保留兩位
    if(parseInt(size)!=size){
      size = size.toFixed(2);
    }

    var itemTemp = '<div class="f-item-info" data-id="'+ fileId +'">\
                      <span class="f-itemName">'+ file.name +'</span>\
                      <span class="f-itemSize">('+ size + unit +')</span>\
                      <span class="f-itemPmgressBar"><span class="f-pmgress"></span></span>\
                      <span class="f-itemSpeed"></span>\
                      <span class="f-itemDel">delete</span>\
                    </div>'
    $showFileContainer.append(itemTemp);
    $showFileItem = $showFileContainer.find(".f-item-info[data-id = "+ fileId +"]")
  }
  
  // ie單個文件過濾限制
  function ie_singleFilefilter(){
    var fPath = $this.val() //文件路徑+文件名
    var fName = fPath.substring(fPath.lastIndexOf("\\") + 1); //文件名
    var extensions = config.fileExtension.split(','); //容許拓展名
    var singleExtension = /\.[a-zA-Z]+$/.exec($this.val())[0].substring(1); // 單文件拓展名
    var isNext = false;

    // 格式限制
    if(extensions && extensions.length){
      for(var i = 0; i < extensions.length; i++){
        if(singleExtension == extensions[i].trim()){
          isNext = true;
        }
      }
    }
    // 判斷isNext和singleExtension,爲空或爲false時提示
    if(!isNext){
      alert('文件格式不正確!');
      clearFile();
      return false;
    }

    var opt={
      iName: $this.prop('id')+' ',
      url: config.url,
      callback: config.callback,
      file: {
        name: fName
      }
    }
    // 動態建立iframe上傳文件
    creatIframe(opt)
  }

  // 建立iframe及表單提交
  function creatIframe(opt){
    var $f_parent = $this.parent();
    var $iframe = $('<iframe name="'+ opt.iName +'" id="' + opt.iName + '" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"/>');
    var $form = $('<form method="post" style="display: none;" target="'+opt.iName+'" action="'+opt.url+'"  name="form_'+opt.iName+'" enctype="multipart/form-data" />');
    // 將控件插入form表單
    $("body").append($iframe);
    // var $form = $('body').find('form');
    $("body").append($form);
    $form.append("<input name='test' type='text'>").append($this);
    // $form.append($("#uploadFile"));

    // 表單提交
    $form.submit();
    // 獲取數據,刪除iframe
    $iframe.ready(function(){
      var data = $iframe.contents().find('body').html();
      if(opt.callback){
        opt.callback(data);
      }
      // 刪除iframe,form
      $iframe.remove();
      $form.remove();
      // 控件放回原始位置
      $f_parent.append($this);
      ie_showFileinfo(opt);

      clearFile();
      return false
    })
  }

  // ie文件顯示
  function ie_showFileinfo(opt){
    var itemTemp = '<div class="f-item-info" data-id="'+ fileId +'">\
      <span class="f-itemName">'+ opt.file.name +'</span>\
      <span class="f-itemDel">delete</span>\
    </div>'
    $showFileContainer.append(itemTemp);
    $showFileItem = $showFileContainer.find(".f-item-info[data-id = "+ fileId +"]")
  }

  //取消上傳
  // abortFunc();
  function abortFunc(){
    // 關閉xhr
    xhr.abort();
    console.log("上傳取消");
  }

  // 清空文件
  function clearFile(){
    if(browserInfo().browser.name == "Internet Explorer" && browserInfo().browser.edition*1 < 11){
      document.getElementById($this.prop("id")).outerHTML += '';
    }else{
      $this.val('');
    }
  }

  // 獲取瀏覽器信息
  var browserInfo = function() {
    var NT = {
        '4.90': 'Windows ME',
        '4.0': 'Windows NT',
        '5.0': 'Windows 2000',
        '5.01': 'Windows 2000 SP1',
        '5.1': 'Windows XP',
        '5.2': 'Windows XP 64-bit / Windows Server 2003',
        '6.0': 'Windows Vista / Windows Server 2008',
        '6.1': 'Windows 7 / Windows Server 2008 R2',
        '6.2': 'Windows 8',
        '6.3': 'Windows 8.1',
        '6.4': 'Windows 10 Technical Preview',
        '10.0': 'Windows 10'
    }
    var userAgent = navigator.userAgent.toLowerCase();
    var platform = navigator.platform;
    var browserName = /(msie\s|trident.*rv:)([\w.]+)/.test(userAgent) ? 'Internet Explorer': (window.opera && window.opera.version ? 'Opera': ((userAgent.indexOf('edge') > -1) ? 'Microsoft Edge': ((userAgent.indexOf('chrome') > -1) ? 'Chrome': ((userAgent.indexOf("firefox") > -1) ? 'Firefox': (userAgent.indexOf('safari') > -1 ? 'Safari': 'Unknown')))));
    var browserVersion = browserName == 'Internet Explorer' ? (userAgent.indexOf('rv:') > -1 ? userAgent.match(/rv:[\d.]+/gi)[0].replace('rv:', '') : userAgent.match(/msie\s[\d.]+/gi)[0].replace('msie ', '')) : (browserName == 'Microsoft Edge' ? userAgent.match(/edge\/[\d.]+/gi)[0].replace('edge/', '') : (browserName == 'Firefox' ? userAgent.match(/firefox\/[\d.]+/gi)[0].replace('firefox/', '') : (browserName == 'Chrome' ? userAgent.match(/chrome\/[\d.]+/gi)[0].replace('chrome/', '') : (browserName == 'Safari' ? userAgent.match(/safari\/[\d.]+/gi)[0].replace('safari/', '') : 'Unknown'))));
    var browserEdition = browserVersion.split('.')[0];
    var kernelName = userAgent.indexOf('trident') > -1 ? 'Trident': userAgent.indexOf('edge') > -1 ? 'Edge': (((userAgent.indexOf('applewebkit') > -1) ? 'Webkit': ((userAgent.indexOf('gecko') > -1) ? 'Gecko': 'Unknown')));
    var kernelVersion = kernelName == 'Trident' ? (userAgent.match(/Trident\/[\d.]+/gi)[0].replace('Trident/', '')) : (browserName == 'Firefox' ? userAgent.match(/gecko\/[\d.]+/gi)[0].replace('gecko/', '') : ((browserName == 'Chrome' || browserName == 'Safari') ? userAgent.match(/applewebkit\/[\d.]+/gi)[0].replace('applewebkit/', '') : (browserName == 'Microsoft Edge' ? userAgent.match(/edge\/[\d.]+/gi)[0].replace('edge/', '') : 'Unknown')));
    var kernelEdition = kernelVersion.split('.')[0];
    var osName = userAgent.indexOf('android') > -1 ? 'Android': (userAgent.indexOf('ipad') > -1 ? 'iOS(iPad)': (userAgent.indexOf('iphone') > -1 ? 'iOS(iPhone)': userAgent.indexOf('windows phone') > -1 ? 'Windows Phone': (((platform == "Win32") || (platform == "Windows") ? 'Microsoft Windows': (navigator.platform == "Mac68K") || ((navigator.platform == "MacPPC") || (navigator.platform == "Macintosh") || (navigator.platform == "MacIntel") ? 'Apple Mac': 'Unknown')))));
    var osEdition = osName == 'Android' ? userAgent.match(/android\s[\d.]+/gi)[0].replace('android ', '') : ((osName == 'iOS(iPad)' || osName == 'iOS(iPhone)') ? userAgent.match(/os\s[\d_]+/gi)[0].replace('os ', '').replace('_', '.') : (osName == 'Windows Phone' ? userAgent.match(/windows\sphone\s[\d.]+/gi)[0].replace('windows phone ', '').replace('_', '.') : (osName == 'Microsoft Windows' ? (NT[userAgent.match(/windows\snt\s[\d.]+/gi)[0].replace('windows nt ', '')] ? NT[userAgent.match(/windows\snt\s[\d.]+/gi)[0].replace('windows nt ', '')] : 'Unknown') : 'Unknown')));
    return {
        browser: {
            name: browserName,
            edition: browserEdition,
            version: browserVersion
        },
        kernel: {
            name: kernelName,
            edition: kernelEdition,
            version: kernelVersion
        },
        os: {
            name: osName,
            edition: osEdition
        }
    };
  }
})(jQuery)
相關文章
相關標籤/搜索