jquery.Huploadify.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. (function ($) {
  2. $.fn.uploadify = function (opts) {
  3. var itemTemp = '<div id="${fileID}" class="uploadify-queue-item"><div class="uploadify-progress"><div class="uploadify-progress-bar"></div></div><span class="up_filename">${fileName}</span><a href="javascript:void(0);" class="uploadbtn">上传</a><a href="javascript:void(0);" class="delfilebtn">删除</a></div>';
  4. var defaults = {
  5. fileTypeExts: '*.*',//允许上传的文件类型,格式'*.jpg;*.doc'
  6. uploader: '',//文件提交的地址
  7. auto: true,//是否开启自动上传
  8. method: 'post',//发送请求的方式,get或post
  9. multi: true,//是否允许选择多个文件
  10. formData: null,//发送给服务端的参数,格式:{key1:value1,key2:value2}
  11. fileObjName: 'fileData',//在后端接受文件的参数名称,如PHP中的$_FILES['file']
  12. fileSizeLimit: 1024000,//允许上传的文件大小,单位KB
  13. showUploadedPercent: true,//是否实时显示上传的百分比,如20%
  14. showUploadedSize: false,//是否实时显示已上传的文件大小,如1M/2M
  15. buttonText: '选择文件',//上传按钮上的文字
  16. removeTimeout: 1000,//上传完成后进度条的消失时间,单位毫秒
  17. itemTemplate: itemTemp,//上传队列显示的模板
  18. onUploadStart: null,//上传开始时的动作
  19. onUploadSuccess: null,//上传成功的动作
  20. onUploadComplete: null,//上传完成的动作
  21. onUploadError: null, //上传失败的动作
  22. onInit: null,//初始化时的动作
  23. onCancel: null,//删除掉某个文件后的回调函数,可传入参数file
  24. onClearQueue: null,//清空上传队列后的回调函数,在调用cancel并传入参数*时触发
  25. onDestroy: null,//在调用destroy方法时触发
  26. onSelect: null,//选择文件后的回调函数,可传入参数file
  27. onQueueComplete: null,//队列中的所有文件上传完成后触发
  28. queueID:false
  29. }
  30. var option = $.extend(defaults, opts);
  31. //定义一个通用函数集合
  32. var F = {
  33. //将文件的单位由bytes转换为KB或MB,若第二个参数指定为true,则永远转换为KB
  34. formatFileSize: function (size, withKB) {
  35. if (size > 1024 * 1024 && !withKB) {
  36. size = (Math.round(size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
  37. }
  38. else {
  39. size = (Math.round(size * 100 / 1024) / 100).toString() + 'KB';
  40. }
  41. return size;
  42. },
  43. //将输入的文件类型字符串转化为数组,原格式为*.jpg;*.png
  44. getFileTypes: function (str) {
  45. var result = [];
  46. var arr1 = str.split(";");
  47. for (var i = 0, len = arr1.length; i < len; i++) {
  48. result.push(arr1[i].split(".").pop());
  49. }
  50. return result;
  51. },
  52. ////根据文件序号获取文件
  53. getFile: function (index, files) {
  54. for (var i = 0; i < files.length; i++) {
  55. if (files[i].index == index) {
  56. return files[i];
  57. }
  58. }
  59. return null;
  60. }
  61. };
  62. var returnObj = null;
  63. this.each(function (index, element) {
  64. var _this = $(element);
  65. var _queue = option.queueID ? $("#" + option.queueID) : _this;
  66. var instanceNumber = $('.uploadify').length + 1;
  67. var uploadManager = {
  68. container: _this,
  69. filteredFiles: [],//过滤后的文件数组
  70. init: function () {
  71. var inputStr = '<input id="select_btn_' + instanceNumber + '" class="selectbtn" style="display:none;" type="file" name="fileselect[]"';
  72. inputStr += option.multi ? ' multiple' : '';
  73. inputStr += ' accept=".';
  74. inputStr += F.getFileTypes(option.fileTypeExts).join(",");
  75. inputStr += '"/>';
  76. inputStr += '<a id="file_upload_' + instanceNumber + '-button" href="javascript:void(0)" class="uploadify-button ' + option.buttonClass + '">';
  77. inputStr += option.buttonText;
  78. inputStr += '</a>';
  79. var uploadFileListStr = "";
  80. var uploadFileListStr = '<div id="file_upload_' + instanceNumber + '-queue" class="uploadify-queue"></div>';
  81. if (option.queueID) {
  82. $("#" + option.queueID).append(uploadFileListStr);
  83. uploadFileListStr = "";
  84. }
  85. _this.append(inputStr + uploadFileListStr);
  86. //初始化返回的实例
  87. returnObj = {
  88. instanceNumber: instanceNumber,
  89. upload: function (fileIndex) {
  90. if (fileIndex === '*') {
  91. for (var i = 0, len = uploadManager.filteredFiles.length; i < len; i++) {
  92. uploadManager._uploadFile(uploadManager.filteredFiles[i]);
  93. }
  94. }
  95. else {
  96. var file = F.getFile(fileIndex, uploadManager.filteredFiles);
  97. file && uploadManager._uploadFile(file);
  98. }
  99. },
  100. cancel: function (fileIndex) {
  101. if (fileIndex === '*') {
  102. var len = uploadManager.filteredFiles.length;
  103. for (var i = len - 1; i >= 0; i--) {
  104. uploadManager._deleteFile(uploadManager.filteredFiles[i]);
  105. }
  106. option.onClearQueue && option.onClearQueue(len);
  107. }
  108. else {
  109. var file = F.getFile(fileIndex, uploadManager.filteredFiles);
  110. file && uploadManager._deleteFile(file);
  111. }
  112. },
  113. disable: function (instanceID) {
  114. var parent = instanceID ? $('file_upload_' + instanceID + '-button') : $('body');
  115. parent.find('.uploadify-button').css('background-color', '#888').off('click');
  116. },
  117. ennable: function (instanceID) {
  118. //点击上传按钮时触发file的click事件
  119. var parent = instanceID ? $('file_upload_' + instanceID + '-button') : $('body');
  120. parent.find('.uploadify-button').css('background-color', '#707070').on('click', function () {
  121. parent.find('.selectbtn').trigger('click');
  122. });
  123. },
  124. destroy: function () {
  125. uploadManager.container.html('');
  126. uploadManager = null;
  127. option.onDestroy && option.onDestroy();
  128. },
  129. settings: function (name, value) {
  130. if (arguments.length == 1) {
  131. return option[name];
  132. }
  133. else {
  134. if (name == 'formData') {
  135. option.formData = $.extend(option.formData, value);
  136. }
  137. else {
  138. option[name] = value;
  139. }
  140. }
  141. },
  142. Huploadify: function () {
  143. var method = arguments[0];
  144. if (method in this) {
  145. Array.prototype.splice.call(arguments, 0, 1);
  146. this[method].apply(this[method], arguments);
  147. }
  148. }
  149. };
  150. //文件选择控件选择
  151. var fileInput = this._getInputBtn();
  152. if (fileInput.length > 0) {
  153. fileInput.change(function (e) {
  154. uploadManager._getFiles(e);
  155. });
  156. }
  157. //点击选择文件按钮时触发file的click事件
  158. _this.find('.uploadify-button').on('click', function () {
  159. _this.find('.selectbtn').trigger('click');
  160. });
  161. option.onInit && option.onInit(returnObj);
  162. },
  163. _filter: function (files) { //选择文件组的过滤方法
  164. var arr = [];
  165. var typeArray = F.getFileTypes(option.fileTypeExts);
  166. if (typeArray.length > 0) {
  167. for (var i = 0, len = files.length; i < len; i++) {
  168. var f = files[i];
  169. if (parseInt(F.formatFileSize(f.size, true)) <= option.fileSizeLimit) {
  170. if ($.inArray('*', typeArray) >= 0 || $.inArray(f.name.split('.').pop(), typeArray) >= 0) {
  171. arr.push(f);
  172. }
  173. else {
  174. alert('文件 "' + f.name + '" 类型不允许!');
  175. }
  176. }
  177. else {
  178. alert('文件 "' + f.name + '" 大小超出限制!');
  179. continue;
  180. }
  181. }
  182. }
  183. return arr;
  184. },
  185. _getInputBtn: function () {
  186. return _this.find('.selectbtn');
  187. },
  188. _getFileList: function () {
  189. return _queue.find('.uploadify-queue');
  190. },
  191. //根据选择的文件,渲染DOM节点
  192. _renderFile: function (file) {
  193. var $html = $(option.itemTemplate.replace(/\${fileID}/g, 'fileupload_' + instanceNumber + '_' + file.index).replace(/\${fileName}/g, file.name).replace(/\${fileSize}/g, F.formatFileSize(file.size)).replace(/\${instanceID}/g, _this.attr('id')));
  194. //如果是非自动上传,显示上传按钮
  195. if (!option.auto) {
  196. $html.find('.uploadbtn').css('display', 'inline-block');
  197. }
  198. uploadManager._getFileList().append($html);
  199. //判断是否显示已上传文件大小
  200. if (option.showUploadedSize) {
  201. var num = '<span class="progressnum"><span class="uploadedsize">0KB</span>/<span class="totalsize">${fileSize}</span></span>'.replace(/\${fileSize}/g, F.formatFileSize(file.size));
  202. $html.find('.uploadify-progress').after(num);
  203. }
  204. //判断是否显示上传百分比
  205. if (option.showUploadedPercent) {
  206. var percentText = '<span class="up_percent">0%</span>';
  207. $html.find('.uploadify-progress').after(percentText);
  208. }
  209. //触发select动作
  210. option.onSelect && option.onSelect(file);
  211. //判断是否是自动上传
  212. if (option.auto) {
  213. uploadManager._uploadFile(file);
  214. }
  215. else {
  216. //如果配置非自动上传,绑定上传事件
  217. $html.find('.uploadbtn').on('click', function () {
  218. if (!$(this).hasClass('.disabledbtn')) {
  219. $(this).addClass('.disabledbtn');
  220. uploadManager._uploadFile(file);
  221. }
  222. });
  223. }
  224. //为删除文件按钮绑定删除文件事件
  225. $html.find('.delfilebtn').on('click', function () {
  226. if (!$(this).hasClass('.disabledbtn')) {
  227. $(this).addClass('.disabledbtn');
  228. uploadManager._deleteFile(file);
  229. }
  230. });
  231. },
  232. //获取选择后的文件
  233. _getFiles: function (e) {
  234. var files = e.target.files;
  235. files = uploadManager._filter(files);
  236. var fileCount = _queue.find('.uploadify-queue .uploadify-queue-item').length;//队列中已经有的文件个数
  237. for (var i = 0, len = files.length; i < len; i++) {
  238. files[i].index = ++fileCount;
  239. files[i].status = 0;//标记为未开始上传
  240. uploadManager.filteredFiles.push(files[i]);
  241. var l = uploadManager.filteredFiles.length;
  242. uploadManager._renderFile(uploadManager.filteredFiles[l - 1]);
  243. }
  244. },
  245. //删除文件
  246. _deleteFile: function (file) {
  247. for (var i = 0, len = uploadManager.filteredFiles.length; i < len; i++) {
  248. var f = uploadManager.filteredFiles[i];
  249. if (f.index == file.index) {
  250. uploadManager.filteredFiles.splice(i, 1);
  251. _queue.find('#fileupload_' + instanceNumber + '_' + file.index).fadeOut();
  252. option.onCancel && option.onCancel(file);
  253. break;
  254. }
  255. }
  256. },
  257. //校正上传完成后的进度条误差
  258. _regulateView: function (file) {
  259. var thisfile = _queue.find('#fileupload_' + instanceNumber + '_' + file.index);
  260. thisfile.find('.uploadify-progress-bar').css('width', '100%');
  261. option.showUploadedSize && thisfile.find('.uploadedsize').text(thisfile.find('.totalsize').text());
  262. option.showUploadedPercent && thisfile.find('.up_percent').text('100%');
  263. },
  264. onProgress: function (file, loaded, total) {
  265. var eleProgress = _queue.find('#fileupload_' + instanceNumber + '_' + file.index + ' .uploadify-progress');
  266. var percent = (loaded / total * 100).toFixed(2) + '%';
  267. if (option.showUploadedSize) {
  268. eleProgress.nextAll('.progressnum .uploadedsize').text(F.formatFileSize(loaded));
  269. eleProgress.nextAll('.progressnum .totalsize').text(F.formatFileSize(total));
  270. }
  271. if (option.showUploadedPercent) {
  272. eleProgress.nextAll('.up_percent').text(percent);
  273. }
  274. eleProgress.children('.uploadify-progress-bar').css('width', percent);
  275. },
  276. _allFilesUploaded: function () {
  277. var queueData = {
  278. uploadsSuccessful: 0,
  279. uploadsErrored: 0
  280. };
  281. for (var i = 0, len = uploadManager.filteredFiles.length; i < len; i++) {
  282. var s = uploadManager.filteredFiles[i].status;
  283. if (s === 0 || s === 1) {
  284. queueData = false;
  285. break;
  286. }
  287. else if (s === 2) {
  288. queueData.uploadsSuccessful++;
  289. }
  290. else if (s === 3) {
  291. queueData.uploadsErrored++;
  292. }
  293. }
  294. return queueData;
  295. },
  296. //上传文件
  297. _uploadFile: function (file) {
  298. var xhr = null;
  299. try {
  300. xhr = new XMLHttpRequest();
  301. } catch (e) {
  302. xhr = ActiveXobject("Msxml12.XMLHTTP");
  303. }
  304. if (xhr.upload) {
  305. // 上传中
  306. xhr.upload.onprogress = function (e) {
  307. uploadManager.onProgress(file, e.loaded, e.total);
  308. };
  309. xhr.onreadystatechange = function (e) {
  310. if (xhr.readyState == 4) {
  311. if (xhr.status == 200) {
  312. uploadManager._regulateView(file);
  313. file.status = 2;//标记为上传成功
  314. option.onUploadSuccess && option.onUploadSuccess(file, "", xhr.responseText);
  315. //在指定的间隔时间后删掉进度条
  316. setTimeout(function () {
  317. _this.find('#fileupload_' + instanceNumber + '_' + file.index).fadeOut();
  318. }, option.removeTimeout);
  319. }
  320. else {
  321. file.status = 3;//标记为上传失败
  322. option.onUploadError && option.onUploadError(file, xhr.responseText);
  323. }
  324. option.onUploadComplete && option.onUploadComplete(file, xhr.responseText);
  325. //检测队列中的文件是否全部上传完成,执行onQueueComplete
  326. if (option.onQueueComplete) {
  327. var queueData = uploadManager._allFilesUploaded();
  328. queueData && option.onQueueComplete(queueData);
  329. }
  330. //清除文件选择框中的已有值
  331. uploadManager._getInputBtn().val('');
  332. }
  333. }
  334. if (file.status === 0) {
  335. console.log(file);
  336. file.status = 1;//标记为正在上传
  337. option.onUploadStart && option.onUploadStart(file);
  338. // 开始上传
  339. xhr.open(option.method, option.uploader, true);
  340. xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  341. var fd = new FormData();
  342. fd.append(option.fileObjName, file);
  343. if (option.formData) {
  344. for (key in option.formData) {
  345. fd.append(key, option.formData[key]);
  346. }
  347. }
  348. xhr.send(fd);
  349. }
  350. }
  351. }
  352. };
  353. uploadManager.init();
  354. });
  355. return returnObj;
  356. }
  357. })(jQuery)