兼容IE低版本的文件上传解决方案
文件上传兼容简直头疼,为此特意封装了个方法,支持IE低版本(>=7)上传及现代浏览器显示上传进度,
此方法只是个hello world,jser可根据自己的需求增减功能及样式
敬上代码,抛砖引玉
调用
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)
方法
(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)