现在工作中使用的文件上传插件是以前的同事使用Flash实现的,最近经常接到客户的反馈说上传插件不能使用,经调查发现是部份客户的浏览器阻止了Flash的运行,需要手动开启Flash才能正常使用,客户体验非常糟糕,毕竟不可能要求每个客户都知道怎么去开启浏览器支持Flash。
思量过后决定把Flash上传修改为JQuery上传。
上代码:
1 ; (function ($, window, document, undefined) { 2 var fileExtentionAcceptConfig = [ 3 { extention: ".3gpp", accept: "audio/3gpp" }, 4 { extention: ".3gpp", accept: "video/3gpp" }, 5 { extention: ".ac3", accept: "audio/ac3" }, 6 { extention: ".asf", accept: "allpication/vnd.ms-asf" }, 7 { extention: ".au", accept: "audio/basic" }, 8 { extention: ".bmp", accept: "image/bmp" }, 9 { extention: ".css", accept: "text/css" }, 10 { extention: ".csv", accept: "text/csv" }, 11 { extention: ".doc", accept: "application/msword" }, 12 { extention: ".dot", accept: "application/msword" }, 13 { extention: ".dtd", accept: "application/xml-dtd" }, 14 { extention: ".dwg", accept: "image/vnd.dwg" }, 15 { extention: ".dxf", accept: "image/vnd.dxf" }, 16 { extention: ".gif", accept: "image/gif" }, 17 { extention: ".htm", accept: "text/html" }, 18 { extention: ".html", accept: "text/html" }, 19 { extention: ".jp2", accept: "image/jp2" }, 20 { extention: ".jpe", accept: "image/jpeg" }, 21 { extention: ".jpeg", accept: "image/jpeg" }, 22 { extention: ".jpg", accept: "image/jpeg" }, 23 { extention: ".js", accept: "text/javascript" }, 24 { extention: ".js", accept: "application/javascript" }, 25 { extention: ".json", accept: "application/json" }, 26 { extention: ".mp2", accept: "audio/mpeg" }, 27 { extention: ".mp2", accept: "video/mpeg" }, 28 { extention: ".mp3", accept: "audio/mpeg" }, 29 { extention: ".mp4", accept: "audio/mp4" }, 30 { extention: ".mp4", accept: "video/mp4" }, 31 { extention: ".mpeg", accept: "video/mpeg" }, 32 { extention: ".mpg", accept: "video/mpeg" }, 33 { extention: ".mpp", accept: "application/vnd.ms-project" }, 34 { extention: ".ogg", accept: "application/ogg" }, 35 { extention: ".ogg", accept: "audio/ogg" }, 36 { extention: ".pdf", accept: "application/pdf" }, 37 { extention: ".png", accept: "image/png" }, 38 { extention: ".pot", accept: "application/vnd.ms-powerpoint" }, 39 { extention: ".pps", accept: "application/vnd.ms-powerpoint" }, 40 { extention: ".ppt", accept: "application/vnd.ms-powerpoint" }, 41 { extention: ".rtf", accept: "application/rtf" }, 42 { extention: ".rtf", accept: "text/rtf" }, 43 { extention: ".svf", accept: "image/vnd.svf" }, 44 { extention: ".tif", accept: "image/tiff" }, 45 { extention: ".tiff", accept: "image/tiff" }, 46 { extention: ".txt", accept: "text/plain" }, 47 { extention: ".wdb", accept: "application/vnd.ms-works" }, 48 { extention: ".wps", accept: "application/vnd.ms-works" }, 49 { extention: ".xhtml", accept: "application/xhtml+xml" }, 50 { extention: ".xlc", accept: "application/vnd.ms-excel" }, 51 { extention: ".xlm", accept: "application/vnd.ms-excel" }, 52 { extention: ".xls", accept: "application/vnd.ms-excel" }, 53 { extention: ".xlt", accept: "application/vnd.ms-excel" }, 54 { extention: ".xlw", accept: "application/vnd.ms-excel" }, 55 { extention: ".xml", accept: "text/xml" }, 56 { extention: ".xml", accept: "application/xml" }, 57 { extention: ".zip", accept: "aplication/zip" }, 58 { extention: ".xlsx", accept: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" } 59 ]; 60 61 var fileTypeConfig = [ 62 { id: 1, name: "商品图片", code: "product" }, 63 { id: 2, name: "PC端装修图片", code: "template" }, 64 { id: 3, name: "其它图片", code: "other" }, 65 { id: 4, name: "手机端装修图片", code: "H5Decorating" }, 66 { id: 5, name: "手机端装修图片", code: "APPDecorating" }, 67 { id: 6, name: "订单相关图片(退货、换货)", code: "Order" }, 68 { id: 7, name: "会员营业执照", code: "UserBusinessLicense" }, 69 { id: 8, name: "会员身份证", code: "UserIDCard" }, 70 { id: 9, name: "试装会员", code: "TrailUser" }, 71 { id: 10, name: "建议反馈", code: "Suggest" }, 72 { id: 11, name: "会员", code: "User" }, 73 { id: 12, name: "设置", code: "Site" }, 74 { id: 13, name: "Childmap", code: "Childmap" } 75 ]; 76 77 var jqueryUpload = function (ele, opt) { 78 var $this = this; 79 80 $this.$element = $(ele); 81 $this._default = { 82 uploadUrl: "/controls/Upload.ashx", 83 buttonStyle: { 84 "display": "inline-block", 85 "background-color": "#EC7B65", 86 "color": "white", 87 "padding": "4px 10px", 88 "border-radius": "2px", 89 "cursor": "pointer", 90 "font-size": "12px", 91 "line-height": "18px" 92 }, 93 offerId: null,//客户ID 94 uploadFolderId: null,//文件夹ID 95 uploadFolderName: null,//文件夹名称,上传路径='uploads/类型code/uploadName' 96 fileType: null,//文件类型1|2|3... 97 noThumb: true,//不生成缩略图 98 waterMark: null,//是否生成水印 99 fileCount: 1, 100 maxSize: 1024,//图片最大尺寸,单位KB;默认1M=1024*1024 101 allowFileType: null,//支持的文件类型,可为后缀名数组:['.jpg', '.png'...],也可以是字符串表式一类文件:'image'|'audio'... 102 multiple: false, 103 onError: null, 104 onSelected: null, 105 onProcess: null, 106 onUploaded: null 107 }; 108 $this.option = $.extend({}, true, $this._default, opt); 109 if ($$.isString($this.option.allowFileType)) { 110 $this.option.allowFileType = $$.sae(fileExtentionAcceptConfig) 111 .findAll(function (x) { return $$.soe(x.accept).startWith($this.option.allowFileType); }) 112 .select(function (x) { return x.extention; }) 113 .toArray(); 114 } 115 116 $this.controlId = $this.generateId(); 117 $this.initControl(); 118 } 119 120 jqueryUpload.prototype = { 121 resetOption: function (option) { 122 var $this = this; 123 124 $this.option = $.extend($this.option, option); 125 $this.initControl(); 126 }, 127 initControl: function () { 128 var $this = this; 129 130 var html = "\ 131 <div id='ju-" + $this.controlId + "' class='ju-container'>"; 132 $this.$filecontrolHtml = "\ 133 <input type='file'"; 134 if ($$.isArray($this.option.allowFileType)) { 135 var accepts = $$.sae(fileExtentionAcceptConfig) 136 .findAll(function (x) { return $$.sae($this.option.allowFileType).any(function (y) { return $$.compare(x.extention, y, true) == 0 }); }) 137 .select(function (x) { return x.accept; }) 138 .distinct() 139 .toArray(); 140 $this.$filecontrolHtml += " accept='" + accepts.join(',') + "'"; 141 } 142 if ($this.option.multiple) { 143 $this.$filecontrolHtml += " multiple='multiple'"; 144 } 145 $this.$filecontrolHtml += " style='display:none;' />"; 146 html += "\ 147 <span class='ju-upload'>上传</span>\ 148 </div>"; 149 $this.$element.html(html); 150 151 $this.$container = $this.$element.find(".ju-container"); 152 $this.resetInputControl(); 153 $this.$uploadbutton = $this.$container.find(".ju-upload"); 154 if ($$.isObject($this.option.buttonStyle)) { 155 $this.$uploadbutton.css($this.option.buttonStyle); 156 $this.$uploadbutton.hover(function () { 157 $this.$uploadbutton.css({ 158 "background-color": "#EF8E7C" 159 }); 160 }, function () { 161 $this.$uploadbutton.css({ 162 "background-color": "#EC7B65" 163 }); 164 }); 165 } else { 166 $this.$uploadbutton.addClass($this.option.buttonStyle); 167 } 168 169 $this.$uploadbutton.click(function () { 170 $this.$filecontrol.click(); 171 }); 172 }, 173 resetInputControl: function () { 174 var $this = this; 175 176 if (!$$.isNullOrUndefined($this.$filecontrol)) { 177 $this.$filecontrol.remove(); 178 } 179 180 $this.$container.append($this.$filecontrolHtml); 181 $this.$filecontrol = $this.$container.find("input[type='file']"); 182 $this.$filecontrol.change(function () { 183 $this.fileSelected(); 184 }); 185 }, 186 fileSelected: function () { 187 var $this = this; 188 189 var aeFile = $$.ae($this.$filecontrol[0].files); 190 191 if (aeFile.any(function (x) { 192 var fileExtention = $$.getFileExtention(x.name); 193 return !$$.sae($this.option.allowFileType).any(function (y) { return $$.compare(y, fileExtention, true) == 0; }); 194 })) { 195 $this.error("不支持的文件类型!"); 196 return; 197 } 198 199 if (aeFile.any(function (x) { return x.size > $this.option.maxSize * 1024; })) { 200 $this.error("文件大小不得超过" + ($this.option.maxSize >= 1024 ? $$.soe($this.option.maxSize / 1024).round(2, $$.enumeration.roundType.floor) + "MB" : $this.option.maxSize + "KB")); 201 return; 202 } 203 204 $.xtcShowLoading("上传中。。。"); 205 $.when(aeFile.forEachAsync(function (x) { 206 if ($$.isFunction($this.option.onSelected)) { 207 var reader = new FileReader(); 208 reader.onload = function (e) { 209 var $img = $("<img />"); 210 //$img.attr("src", e.target.result); 211 //$img.attr("data-url", window.URL.createObjectURL(file)); 212 var imageUrl = window.URL.createObjectURL(x); 213 $img.attr("src", imageUrl).css("cursor", "pointer"); 214 $this.option.onSelected($img); 215 $img.click(function () { 216 window.open(imageUrl); 217 }); 218 } 219 reader.readAsDataURL(x); 220 } 221 222 return $this.upload(x); 223 }, $)).done(function (data) { 224 data = $$.sae(data) 225 .findAll(function (x) { return !$$.isNullOrWhiteSpace(x); }) 226 .toArray(); 227 if (data.length == 0) { 228 return; 229 } else if (data.length == 1) { 230 $this.option.onUploaded(data[0]) 231 } else { 232 $this.option.onUploaded(data); 233 } 234 235 $this.resetInputControl(); 236 }).always(function () { 237 $.xtcHideLoading(); 238 }); 239 }, 240 error: function (msg) { 241 var $this = this; 242 243 if ($$.isFunction($this.option.onError)) { 244 $this.option.onError(msg); 245 } 246 247 $this.resetInputControl(); 248 }, 249 process: function (evt) { 250 var $this = this; 251 252 if ($$.isFunction($this.option.onProcess)) { 253 $this.option.onProcess(evt.total, evt.loaded); 254 } 255 }, 256 upload: function (file) { 257 var defer = $.Deferred(); 258 259 var $this = this; 260 261 var formData = new FormData(); 262 formData.append("file", file); 263 264 try { 265 var params = []; 266 if (!$$.isNullOrUndefined($this.option.offerId)) { 267 params.push("offerid=" + $this.option.offerId); 268 if ($$.soe($this.option.offerId).toInt() > 0) { 269 params.push("isoffer=1"); 270 } 271 } 272 if (!$$.isNullOrUndefined($this.option.uploadFolderId)) { 273 params.push("cid=" + $this.option.uploadFolderId); 274 } 275 var uploadDir = "uploads"; 276 var fileType = null; 277 if (!$$.isNullOrUndefined($this.option.fileType)) { 278 var fileTypeId = $$.soe($this.option.fileType).toInt(); 279 params.push("type=" + fileTypeId); 280 var fileType = $$.sae(fileTypeConfig) 281 .firstOrDefault(function (x) { return x.id == fileTypeId; }); 282 } 283 if (fileType != null) { 284 uploadDir += "/" + fileType.code; 285 } else { 286 uploadDir += "/unknown"; 287 } 288 if (!$$.isNullOrWhiteSpace($this.option.uploadFolderName)) { 289 uploadDir += "/" + $this.option.uploadFolderName; 290 } 291 params.push("upload_dir=" + uploadDir); 292 if (!$$.isNullOrUndefined($this.option.noThumb)) { 293 params.push("no_thumb=" + ($this.option.noThumb ? 1 : 0)); 294 } 295 if (!$$.isNullOrUndefined($this.option.waterMark)) { 296 params.push("WaterMark=" + ($this.option.waterMark ? 1 : 0)); 297 } 298 $.ajax({ 299 url: $this.option.uploadUrl + "?" + params.join('&'), 300 type: "POST", 301 data: formData, 302 async: true, 303 contentType: false, 304 processData: false, 305 dataType: "html", 306 xhr: function () { 307 var xhr = $.ajaxSettings.xhr(); 308 xhr.upload.addEventListener("progress", function (evt) { $this.process(evt); }, false); 309 return xhr; 310 } 311 }).done(function (data) { 312 if ($$.isNullOrUndefined(data)) { 313 $this.error("上传失败,未知错误!"); 314 defer.resolve(""); 315 } else if (data.indexOf(".") <= 0) { 316 $this.error(data); 317 defer.resolve(""); 318 } else if ($$.isFunction($this.option.onUploaded)) { 319 defer.resolve(data); 320 } 321 }).fail(function (err) { 322 if (typeof (err) == "object" && err.constructor == Object && err.responseText) { 323 $this.error(err.responseText); 324 } else { 325 $this.error(err); 326 } 327 defer.resolve(""); 328 }); 329 } 330 catch (err) { 331 if (typeof (err) == "object" && err.constructor == Object && err.responseText) { 332 $this.error(err.responseText); 333 } else { 334 $this.error(err); 335 } 336 defer.resolve(""); 337 } 338 339 return defer; 340 }, 341 generateId: function () { 342 var guid = ""; 343 for (var i = 1; i <= 32; i++) { 344 var n = Math.floor(Math.random() * 16.0).toString(16); 345 guid += n; 346 if ((i == 8) || (i == 12) || (i == 16) || (i == 20)) 347 guid += "-"; 348 } 349 return guid; 350 } 351 } 352 353 $.fn.xtcUpload = function (option) { 354 return new jqueryUpload(this, option); 355 } 356 })(jQuery, window, document);
如何使用?
<script type="text/javascript" src="http://jsl.solomon-yu.cn/JSE/jsExtension.min.js"></script><!--使用了上一篇随笔里编写的JS扩展插件,需要引入--> <script type="text/javascript" src="/common_script/jqueryUpload.js"></script> <script type="text/javascript"> $(function () { var uploadControl = $(".uploadTest").xtcUpload({ buttonStyle: "upload-button",//按钮样式,可以是一个css键值对实体,也可以是一个class名称 uploadFolderId: 220,//上传文件夹ID uploadFolderName: '10月20日活动页',//上传文件夹名称 fileType: 3,//文件类型,对应于JS文件中的fileTypeConfig maxSize: 500,//文件大小限制单位KB allowFileType: [".png", ".jpg"],//支持的文件类型,可为后缀名数组:['.jpg', '.png'...],也可以是字符串表式一类文件:'image'|'audio'... //发生错误时调用的函数 onError: function (msg) { Ecshop.Tool.Hint.Error({ info: msg }); }, //上传时进度条触发事件 onProcess: function (total, loaded) { //百分比 loaded / total * 100 }, //上传完成时触发事件 onUploaded: function (file) { $(".img-before-upload").append("<img src='/" + file + "' />"); } }); //当需要时(如上传文件夹变更)重置上传控件参数 uploadControl.resetOption({ uploadFolderId: 221 }); }); </script> <div class="uploadTest"></div> <div class="img-before-upload"></div>