AjaxUpLoad.js使用实现文件上传

时间:2023-03-14 19:55:44

AjaxUpLoad.js的使用实现无刷新文件上传,如图。

AjaxUpLoad.js使用实现文件上传

图1 文件上传前

AjaxUpLoad.js使用实现文件上传

图2 文件上传后

1、创建页面并编写HTML

[html] view plaincopy
  1. 上传文档:
  2. <div class="uploadFile">
  3. <span id="doc"><input type="text" disabled="disabled" /></span>
  4. <input type="hidden" id="hidFileName"  />
  5. <input type="button" id="btnUploadFile" value="上传" />
  6. <input type="button" id="btnDeleteFile" value="删除"  />
  7. </div>
  8. 上传图片:
  9. <div class="uploadImg">
  10. <img id="imgShow" src="/images/nophoto.gif" />
  11. <input type="hidden" id="hidImgName" />
  12. <input type="button" id="btnUploadImg" value="上传" />
  13. <input type="button" id="btnDeleteImg" value="删除" />
  14. </div>

2、引用AjaxUpload.js文件

[html] view plaincopy
  1. <script src="/js/common/AjaxUpload.js" type="text/javascript"></script>

3、编写JS脚本

[java] view plaincopy
  1. window.onload = function() {
  2. init();  //初始化
  3. }
  4. //初始化
  5. function init() {
  6. //初始化文档上传
  7. var btnFile = document.getElementById("btnUploadFile");
  8. var doc = document.getElementById("doc");
  9. var hidFileName = document.getElementById("hidFileName");
  10. document.getElementById("btnDeleteFile").onclick = function() { DelFile(doc, hidFileName); };
  11. g_AjxUploadFile(btnFile, doc, hidFileName);
  12. //初始化图片上传
  13. var btnImg = document.getElementById("btnUploadImg");
  14. var img = document.getElementById("imgShow");
  15. var hidImgName = document.getElementById("hidImgName");
  16. document.getElementById("btnDeleteImg").onclick = function() { DelImg(img, hidImgName); };
  17. g_AjxUploadImg(btnImg, img, hidImgName);
  18. }
  19. var g_AjxTempDir = "/file/temp/";
  20. //文档上传
  21. function g_AjxUploadFile(btn, doc, hidPut, action) {
  22. var button = btn, interval;
  23. new AjaxUpload(button, {
  24. action: ((action == null || action == undefined) ? '/Common/UploadHandler.ashx?fileType=file' : action),
  25. data: {},
  26. name: 'myfile',
  27. onSubmit: function(file, ext) {
  28. if (!(ext && /^(rar|zip|pdf|pdfx|txt|csv|xls|xlsx|doc|docx|RAR|ZIP|PDF|PDFX|TXT|CSV|XLS|XLSX|DOC|DOCX)$/.test(ext))) {
  29. alert("您上传的文档格式不对,请重新选择!");
  30. return false;
  31. }
  32. },
  33. onComplete: function(file, response) {
  34. flagValue = response;
  35. if (flagValue == "1") {
  36. alert("您上传的文档格式不对,请重新选择!");
  37. }
  38. else if (flagValue == "2") {
  39. alert("您上传的文档大于2M,请重新选择!");
  40. }
  41. else if (flagValue == "3") {
  42. alert("文档上传失败!");
  43. }
  44. else {
  45. hidPut.value = response;
  46. doc.innerHTML="<a href='" + g_AjxTempDir + response + "' target='_blank'>" + response + "</a>";
  47. }
  48. }
  49. });
  50. }
  51. //图片上传
  52. function g_AjxUploadImg(btn, img, hidPut) {
  53. var button = btn, interval;
  54. new AjaxUpload(button, {
  55. action: '/Common/UploadHandler.ashx?fileType=img',
  56. data: {},
  57. name: 'myfile',
  58. onSubmit: function(file, ext) {
  59. if (!(ext && /^(jpg|JPG|png|PNG|gif|GIF)$/.test(ext))) {
  60. alert("您上传的图片格式不对,请重新选择!");
  61. return false;
  62. }
  63. },
  64. onComplete: function(file, response) {
  65. flagValue = response;
  66. if (flagValue == "1") {
  67. alert("您上传的图片格式不对,请重新选择!");
  68. }
  69. else if (flagValue == "2") {
  70. alert("您上传的图片大于200K,请重新选择!");
  71. }
  72. else if (flagValue == "3") {
  73. alert("图片上传失败!");
  74. }
  75. else {
  76. hidPut.value = response;
  77. img.src = g_AjxTempDir + response;
  78. }
  79. }
  80. });
  81. }
  82. //删除文档
  83. function DelFile(doc, hidPut) {
  84. hidPut.value = "";
  85. doc.innerHTML = "<input type=\"text\" disabled=\"disabled\" />";
  86. }
  87. //删除图片
  88. function DelImg(img, hidPut) {
  89. hidPut.value = "";
  90. img.src = "/images/nophoto.gif";
  91. }

4、创建/Common/UploadHandler.ashx处理程序

[csharp] view plaincopy
  1. <%@ WebHandler Language="C#" Class="UploadHandler" %>
  2. using System;
  3. using System.Web;
  4. using System.Text.RegularExpressions;
  5. using System.IO;
  6. public class UploadHandler : IHttpHandler {
  7. private string _filedir = "";    //文件目录
  8. /// <summary>
  9. /// 处理上传文件(1:文件格式不正确、2:文件大小不正确、3:上传失败、文件名称:上传成功)
  10. /// </summary>
  11. /// <param name="context"></param>
  12. public void ProcessRequest (HttpContext context) {
  13. _filedir = context.Server.MapPath(@"/file/temp/");
  14. try
  15. {
  16. string result = "3";
  17. string fileType = context.Request.QueryString["fileType"]; //获取上传文件类型
  18. if (fileType == "file")
  19. {
  20. result = UploadFile(context);  //文档上传
  21. }
  22. else if (fileType == "img")
  23. {
  24. result = UploadImg(context);   //图片上传
  25. }
  26. context.Response.Write(result);
  27. }
  28. catch
  29. {
  30. context.Response.Write("3");//3文件上传失败
  31. }
  32. }
  33. /// <summary>
  34. /// 文档上传
  35. /// </summary>
  36. /// <param name="context"></param>
  37. /// <returns></returns>
  38. private string UploadFile(HttpContext context)
  39. {
  40. int cout = context.Request.Files.Count;
  41. if (cout > 0)
  42. {
  43. HttpPostedFile hpf = context.Request.Files[0];
  44. if (hpf != null)
  45. {
  46. string fileExt = Path.GetExtension(hpf.FileName).ToLower();
  47. //只能上传文件,过滤不可上传的文件类型
  48. string fileFilt = ".rar|.zip|.pdf|.pdfx|.txt|.csv|.xls|.xlsx|.doc|.docx......";
  49. if (fileFilt.IndexOf(fileExt) <= -1)
  50. {
  51. return "1";
  52. }
  53. //判断文件大小
  54. int length = hpf.ContentLength;
  55. if (length > 2097152)
  56. {
  57. return "2";
  58. }
  59. Random rd = new Random();
  60. DateTime nowTime = DateTime.Now;
  61. string newFileName = nowTime.Year.ToString() + nowTime.Month.ToString() + nowTime.Day.ToString() + nowTime.Hour.ToString() + nowTime.Minute.ToString() + nowTime.Second.ToString() + rd.Next(1000, 1000000) + Path.GetExtension(hpf.FileName);
  62. if (!Directory.Exists(_filedir))
  63. {
  64. Directory.CreateDirectory(_filedir);
  65. }
  66. string fileName = _filedir + newFileName;
  67. hpf.SaveAs(fileName);
  68. return newFileName;
  69. }
  70. }
  71. return "3";
  72. }
  73. /// <summary>
  74. /// 图片上传
  75. /// </summary>
  76. /// <param name="context"></param>
  77. /// <returns></returns>
  78. private string UploadImg(HttpContext context)
  79. {
  80. int cout = context.Request.Files.Count;
  81. if (cout > 0)
  82. {
  83. HttpPostedFile hpf = context.Request.Files[0];
  84. if (hpf != null)
  85. {
  86. string fileExt = Path.GetExtension(hpf.FileName).ToLower();
  87. //只能上传文件,过滤不可上传的文件类型
  88. string fileFilt = ".gif|.jpg|.php|.jsp|.jpeg|.png|......";
  89. if (fileFilt.IndexOf(fileExt) <= -1)
  90. {
  91. return "1";
  92. }
  93. //判断文件大小
  94. int length = hpf.ContentLength;
  95. if (length > 204800)
  96. {
  97. return "2";
  98. }
  99. Random rd = new Random();
  100. DateTime nowTime = DateTime.Now;
  101. string newFileName = nowTime.Year.ToString() + nowTime.Month.ToString() + nowTime.Day.ToString() + nowTime.Hour.ToString() + nowTime.Minute.ToString() + nowTime.Second.ToString() + rd.Next(1000, 1000000) + Path.GetExtension(hpf.FileName);
  102. if (!Directory.Exists(_filedir))
  103. {
  104. Directory.CreateDirectory(_filedir);
  105. }
  106. string fileName = _filedir + newFileName;
  107. hpf.SaveAs(fileName);
  108. return newFileName;
  109. }
  110. }
  111. return "3";
  112. }
  113. #region IHttpHandler 成员
  114. public bool IsReusable
  115. {
  116. get { throw new NotImplementedException(); }
  117. }
  118. #endregion
  119. }

附件1:页面CSS样式

  1. /*上传文件*/
  2. .uploadFile{margin-bottom:10px;}
  3. /*上传图片*/
  4. .uploadImg{}
  5. .uploadImg img{width:102px; height:64px; border:1px solid #CCCCCC; display: block;}

附件2:AjaxUpload.js文件

[javascript] view plaincopy
  1. /**
  2. * AJAX Upload ( http://valums.com/ajax-upload/ )
  3. * Copyright (c) Andris Valums
  4. * Licensed under the MIT license ( http://valums.com/mit-license/ )
  5. * Thanks to Gary Haran, David Mark, Corey Burns and others for contributions
  6. */
  7. (function () {
  8. /* global window */
  9. /* jslint browser: true, devel: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true */
  10. /**
  11. * Wrapper for FireBug's console.log
  12. */
  13. function log() {
  14. if (typeof(console) != 'undefined' && typeof(console.log) == 'function') {
  15. Array.prototype.unshift.call(arguments, '[Ajax Upload]');
  16. console.log(Array.prototype.join.call(arguments, ' '));
  17. }
  18. }
  19. /**
  20. * Attaches event to a dom element.
  21. * @param {Element} el
  22. * @param type event name
  23. * @param fn callback This refers to the passed element
  24. */
  25. function addEvent(el, type, fn) {
  26. if (el.addEventListener) {
  27. el.addEventListener(type, fn, false);
  28. } else if (el.attachEvent) {
  29. el.attachEvent('on' + type, function () {
  30. fn.call(el);
  31. });
  32. } else {
  33. throw new Error('not supported or DOM not loaded');
  34. }
  35. }
  36. /**
  37. * Attaches resize event to a window, limiting
  38. * number of event fired. Fires only when encounteres
  39. * delay of 100 after series of events.
  40. *
  41. * Some browsers fire event multiple times when resizing
  42. * http://www.quirksmode.org/dom/events/resize.html
  43. *
  44. * @param fn callback This refers to the passed element
  45. */
  46. function addResizeEvent(fn) {
  47. var timeout;
  48. addEvent(window, 'resize', function () {
  49. if (timeout) {
  50. clearTimeout(timeout);
  51. }
  52. timeout = setTimeout(fn, 100);
  53. });
  54. }
  55. // Needs more testing, will be rewriten for next version
  56. // getOffset function copied from jQuery lib (http://jquery.com/)
  57. if (document.documentElement.getBoundingClientRect) {
  58. // Get Offset using getBoundingClientRect
  59. // http://ejohn.org/blog/getboundingclientrect-is-awesome/
  60. var getOffset = function (el) {
  61. var box = el.getBoundingClientRect();
  62. var doc = el.ownerDocument;
  63. var body = doc.body;
  64. var docElem = doc.documentElement; // for ie
  65. var clientTop = docElem.clientTop || body.clientTop || 0;
  66. var clientLeft = docElem.clientLeft || body.clientLeft || 0;
  67. // In Internet Explorer 7 getBoundingClientRect property is treated as physical,
  68. // while others are logical. Make all logical, like in IE8.
  69. var zoom = 1;
  70. if (body.getBoundingClientRect) {
  71. var bound = body.getBoundingClientRect();
  72. zoom = (bound.right - bound.left) / body.clientWidth;
  73. }
  74. if (zoom > 1) {
  75. clientTop = 0;
  76. clientLeft = 0;
  77. }
  78. var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop,
  79. left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft;
  80. return {
  81. top: top,
  82. left: left
  83. };
  84. };
  85. } else {
  86. // Get offset adding all offsets
  87. var getOffset = function (el) {
  88. var top = 0,
  89. left = 0;
  90. do {
  91. top += el.offsetTop || 0;
  92. left += el.offsetLeft || 0;
  93. el = el.offsetParent;
  94. } while (el);
  95. return {
  96. left: left,
  97. top: top
  98. };
  99. };
  100. }
  101. /**
  102. * Returns left, top, right and bottom properties describing the border-box,
  103. * in pixels, with the top-left relative to the body
  104. * @param {Element} el
  105. * @return {Object} Contains left, top, right,bottom
  106. */
  107. function getBox(el) {
  108. var left, right, top, bottom;
  109. var offset = getOffset(el);
  110. left = offset.left;
  111. top = offset.top;
  112. right = left + el.offsetWidth;
  113. bottom = top + el.offsetHeight;
  114. return {
  115. left: left,
  116. right: right,
  117. top: top,
  118. bottom: bottom
  119. };
  120. }
  121. /**
  122. * Helper that takes object literal
  123. * and add all properties to element.style
  124. * @param {Element} el
  125. * @param {Object} styles
  126. */
  127. function addStyles(el, styles) {
  128. for (var name in styles) {
  129. if (styles.hasOwnProperty(name)) {
  130. el.style[name] = styles[name];
  131. }
  132. }
  133. }
  134. /**
  135. * Function places an absolutely positioned
  136. * element on top of the specified element
  137. * copying position and dimentions.
  138. * @param {Element} from
  139. * @param {Element} to
  140. */
  141. function copyLayout(from, to) {
  142. var box = getBox(from);
  143. addStyles(to, {
  144. position: 'absolute',
  145. left: box.left + 'px',
  146. top: box.top + 'px',
  147. width: from.offsetWidth + 'px',
  148. height: from.offsetHeight + 'px'
  149. });
  150. }
  151. /**
  152. * Creates and returns element from html chunk
  153. * Uses innerHTML to create an element
  154. */
  155. var toElement = (function () {
  156. var div = document.createElement('div');
  157. return function (html) {
  158. div.innerHTML = html;
  159. var el = div.firstChild;
  160. return div.removeChild(el);
  161. };
  162. })();
  163. /**
  164. * Function generates unique id
  165. * @return unique id
  166. */
  167. var getUID = (function () {
  168. var id = 0;
  169. return function () {
  170. return 'ValumsAjaxUpload' + id++;
  171. };
  172. })();
  173. /**
  174. * Get file name from path
  175. * @param {String} file path to file
  176. * @return filename
  177. */
  178. function fileFromPath(file) {
  179. return file.replace(/.*(\/|\\)/, "");
  180. }
  181. /**
  182. * Get file extension lowercase
  183. * @param {String} file name
  184. * @return file extenstion
  185. */
  186. function getExt(file) {
  187. return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';
  188. }
  189. function hasClass(el, name) {
  190. var re = new RegExp('\\b' + name + '\\b');
  191. return re.test(el.className);
  192. }
  193. function addClass(el, name) {
  194. if (!hasClass(el, name)) {
  195. el.className += ' ' + name;
  196. }
  197. }
  198. function removeClass(el, name) {
  199. var re = new RegExp('\\b' + name + '\\b');
  200. el.className = el.className.replace(re, '');
  201. }
  202. function removeNode(el) {
  203. el.parentNode.removeChild(el);
  204. }
  205. /**
  206. * Easy styling and uploading
  207. * @constructor
  208. * @param button An element you want convert to
  209. * upload button. Tested dimentions up to 500x500px
  210. * @param {Object} options See defaults below.
  211. */
  212. window.AjaxUpload = function (button, options) {
  213. this._settings = {
  214. // Location of the server-side upload script
  215. action: 'upload.php',
  216. // File upload name
  217. name: 'userfile',
  218. // Additional data to send
  219. data: {},
  220. // Submit file as soon as it's selected
  221. autoSubmit: true,
  222. // The type of data that you're expecting back from the server.
  223. // html and xml are detected automatically.
  224. // Only useful when you are using json data as a response.
  225. // Set to "json" in that case.
  226. responseType: false,
  227. // Class applied to button when mouse is hovered
  228. hoverClass: 'hover',
  229. // Class applied to button when AU is disabled
  230. disabledClass: 'disabled',
  231. // When user selects a file, useful with autoSubmit disabled
  232. // You can return false to cancel upload
  233. onChange: function (file, extension) {},
  234. // Callback to fire before file is uploaded
  235. // You can return false to cancel upload
  236. onSubmit: function (file, extension) {},
  237. // Fired when file upload is completed
  238. // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!
  239. onComplete: function (file, response) {}
  240. };
  241. // Merge the users options with our defaults
  242. for (var i in options) {
  243. if (options.hasOwnProperty(i)) {
  244. this._settings[i] = options[i];
  245. }
  246. }
  247. // button isn't necessary a dom element
  248. if (button.jquery) {
  249. // jQuery object was passed
  250. button = button[0];
  251. } else if (typeof button == "string") {
  252. if (/^#.*/.test(button)) {
  253. // If jQuery user passes #elementId don't break it
  254. button = button.slice(1);
  255. }
  256. button = document.getElementById(button);
  257. }
  258. if (!button || button.nodeType !== 1) {
  259. throw new Error("Please make sure that you're passing a valid element");
  260. }
  261. if (button.nodeName.toUpperCase() == 'A') {
  262. // disable link
  263. addEvent(button, 'click', function (e) {
  264. if (e && e.preventDefault) {
  265. e.preventDefault();
  266. } else if (window.event) {
  267. window.event.returnValue = false;
  268. }
  269. });
  270. }
  271. // DOM element
  272. this._button = button;
  273. // DOM element
  274. this._input = null;
  275. // If disabled clicking on button won't do anything
  276. this._disabled = false;
  277. // if the button was disabled before refresh if will remain
  278. // disabled in FireFox, let's fix it
  279. this.enable();
  280. this._rerouteClicks();
  281. };
  282. // assigning methods to our class
  283. AjaxUpload.prototype = {
  284. setData: function (data) {
  285. this._settings.data = data;
  286. },
  287. disable: function () {
  288. addClass(this._button, this._settings.disabledClass);
  289. this._disabled = true;
  290. var nodeName = this._button.nodeName.toUpperCase();
  291. if (nodeName == 'INPUT' || nodeName == 'BUTTON') {
  292. this._button.setAttribute('disabled', 'disabled');
  293. }
  294. // hide input
  295. if (this._input) {
  296. // We use visibility instead of display to fix problem with Safari 4
  297. // The problem is that the value of input doesn't change if it
  298. // has display none when user selects a file
  299. this._input.parentNode.style.visibility = 'hidden';
  300. }
  301. },
  302. enable: function () {
  303. removeClass(this._button, this._settings.disabledClass);
  304. this._button.removeAttribute('disabled');
  305. this._disabled = false;
  306. },
  307. /**
  308. * Creates invisible file input
  309. * that will hover above the button
  310. * <div><input type='file' /></div>
  311. */
  312. _createInput: function () {
  313. var self = this;
  314. var input = document.createElement("input");
  315. input.setAttribute('type', 'file');
  316. input.setAttribute('name', this._settings.name);
  317. addStyles(input, {
  318. 'position': 'absolute',
  319. // in Opera only 'browse' button
  320. // is clickable and it is located at
  321. // the right side of the input
  322. 'right': 0,
  323. 'margin': 0,
  324. 'padding': 0,
  325. 'fontSize': '480px',
  326. 'cursor': 'pointer'
  327. });
  328. var div = document.createElement("div");
  329. addStyles(div, {
  330. 'display': 'block',
  331. 'position': 'absolute',
  332. 'overflow': 'hidden',
  333. 'margin': 0,
  334. 'padding': 0,
  335. 'opacity': 0,
  336. // Make sure browse button is in the right side
  337. // in Internet Explorer
  338. 'direction': 'ltr',
  339. //Max zIndex supported by Opera 9.0-9.2
  340. 'zIndex': 2147483583
  341. });
  342. // Make sure that element opacity exists.
  343. // Otherwise use IE filter
  344. if (div.style.opacity !== "0") {
  345. if (typeof(div.filters) == 'undefined') {
  346. throw new Error('Opacity not supported by the browser');
  347. }
  348. div.style.filter = "alpha(opacity=0)";
  349. }
  350. addEvent(input, 'change', function () {
  351. if (!input || input.value === '') {
  352. return;
  353. }
  354. // Get filename from input, required
  355. // as some browsers have path instead of it
  356. var file = fileFromPath(input.value);
  357. if (false === self._settings.onChange.call(self, file, getExt(file))) {
  358. self._clearInput();
  359. return;
  360. }
  361. // Submit form when value is changed
  362. if (self._settings.autoSubmit) {
  363. self.submit();
  364. }
  365. });
  366. addEvent(input, 'mouseover', function () {
  367. addClass(self._button, self._settings.hoverClass);
  368. });
  369. addEvent(input, 'mouseout', function () {
  370. removeClass(self._button, self._settings.hoverClass);
  371. // We use visibility instead of display to fix problem with Safari 4
  372. // The problem is that the value of input doesn't change if it
  373. // has display none when user selects a file
  374. input.parentNode.style.visibility = 'hidden';
  375. });
  376. div.appendChild(input);
  377. document.body.appendChild(div);
  378. this._input = input;
  379. },
  380. _clearInput: function () {
  381. if (!this._input) {
  382. return;
  383. }
  384. // this._input.value = ''; Doesn't work in IE6
  385. removeNode(this._input.parentNode);
  386. this._input = null;
  387. this._createInput();
  388. removeClass(this._button, this._settings.hoverClass);
  389. },
  390. /**
  391. * Function makes sure that when user clicks upload button,
  392. * the this._input is clicked instead
  393. */
  394. _rerouteClicks: function () {
  395. var self = this;
  396. // IE will later display 'access denied' error
  397. // if you use using self._input.click()
  398. // other browsers just ignore click()
  399. addEvent(self._button, 'mouseover', function () {
  400. if (self._disabled) {
  401. return;
  402. }
  403. if (!self._input) {
  404. self._createInput();
  405. }
  406. var div = self._input.parentNode;
  407. copyLayout(self._button, div);
  408. div.style.visibility = 'visible';
  409. });
  410. // commented because we now hide input on mouseleave
  411. /**
  412. * When the window is resized the elements
  413. * can be misaligned if button position depends
  414. * on window size
  415. */
  416. //addResizeEvent(function(){
  417. //    if (self._input){
  418. //        copyLayout(self._button, self._input.parentNode);
  419. //    }
  420. //});
  421. },
  422. /**
  423. * Creates iframe with unique name
  424. * @return {Element} iframe
  425. */
  426. _createIframe: function () {
  427. // We can't use getTime, because it sometimes return
  428. // same value in safari :(
  429. var id = getUID();
  430. // We can't use following code as the name attribute
  431. // won't be properly registered in IE6, and new window
  432. // on form submit will open
  433. // var iframe = document.createElement('iframe');
  434. // iframe.setAttribute('name', id);
  435. var iframe = toElement('<iframe src="javascript:false;" name="' + id + '" />');
  436. // src="javascript:false; was added
  437. // because it possibly removes ie6 prompt
  438. // "This page contains both secure and nonsecure items"
  439. // Anyway, it doesn't do any harm.
  440. iframe.setAttribute('id', id);
  441. iframe.style.display = 'none';
  442. document.body.appendChild(iframe);
  443. return iframe;
  444. },
  445. /**
  446. * Creates form, that will be submitted to iframe
  447. * @param {Element} iframe Where to submit
  448. * @return {Element} form
  449. */
  450. _createForm: function (iframe) {
  451. var settings = this._settings;
  452. // We can't use the following code in IE6
  453. // var form = document.createElement('form');
  454. // form.setAttribute('method', 'post');
  455. // form.setAttribute('enctype', 'multipart/form-data');
  456. // Because in this case file won't be attached to request
  457. var form = toElement('<form method="post" enctype="multipart/form-data"></form>');
  458. form.setAttribute('action', settings.action);
  459. form.setAttribute('target', iframe.name);
  460. form.style.display = 'none';
  461. document.body.appendChild(form);
  462. // Create hidden input element for each data key
  463. for (var prop in settings.data) {
  464. if (settings.data.hasOwnProperty(prop)) {
  465. var el = document.createElement("input");
  466. el.setAttribute('type', 'hidden');
  467. el.setAttribute('name', prop);
  468. el.setAttribute('value', settings.data[prop]);
  469. form.appendChild(el);
  470. }
  471. }
  472. return form;
  473. },
  474. /**
  475. * Gets response from iframe and fires onComplete event when ready
  476. * @param iframe
  477. * @param file Filename to use in onComplete callback
  478. */
  479. _getResponse: function (iframe, file) {
  480. // getting response
  481. var toDeleteFlag = false,
  482. self = this,
  483. settings = this._settings;
  484. addEvent(iframe, 'load', function () {
  485. if ( // For Safari
  486. iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" ||
  487. // For FF, IE
  488. iframe.src == "javascript:'<html></html>';") {
  489. // First time around, do not delete.
  490. // We reload to blank page, so that reloading main page
  491. // does not re-submit the post.
  492. if (toDeleteFlag) {
  493. // Fix busy state in FF3
  494. setTimeout(function () {
  495. removeNode(iframe);
  496. },
  497. 0);
  498. }
  499. return;
  500. }
  501. var doc = iframe.contentDocument ? iframe.contentDocument : window.frames[iframe.id].document;
  502. // fixing Opera 9.26,10.00
  503. if (doc.readyState && doc.readyState != 'complete') {
  504. // Opera fires load event multiple times
  505. // Even when the DOM is not ready yet
  506. // this fix should not affect other browsers
  507. return;
  508. }
  509. // fixing Opera 9.64
  510. if (doc.body && doc.body.innerHTML == "false") {
  511. // In Opera 9.64 event was fired second time
  512. // when body.innerHTML changed from false
  513. // to server response approx. after 1 sec
  514. return;
  515. }
  516. var response;
  517. if (doc.XMLDocument) {
  518. // response is a xml document Internet Explorer property
  519. response = doc.XMLDocument;
  520. } else if (doc.body) {
  521. // response is html document or plain text
  522. response = doc.body.innerHTML;
  523. if (settings.responseType && settings.responseType.toLowerCase() == 'json') {
  524. // If the document was sent as 'application/javascript' or
  525. // 'text/javascript', then the browser wraps the text in a <pre>
  526. // tag and performs html encoding on the contents.  In this case,
  527. // we need to pull the original text content from the text node's
  528. // nodeValue property to retrieve the unmangled content.
  529. // Note that IE6 only understands text/html
  530. if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE') {
  531. response = doc.body.firstChild.firstChild.nodeValue;
  532. }
  533. if (response) {
  534. response = eval("(" + response + ")");
  535. } else {
  536. response = {};
  537. }
  538. }
  539. } else {
  540. // response is a xml document
  541. response = doc;
  542. }
  543. settings.onComplete.call(self, file, response);
  544. // Reload blank page, so that reloading main page
  545. // does not re-submit the post. Also, remember to
  546. // delete the frame
  547. toDeleteFlag = true;
  548. // Fix IE mixed content issue
  549. iframe.src = "javascript:'<html></html>';";
  550. });
  551. },
  552. /**
  553. * Upload file contained in this._input
  554. */
  555. submit: function () {
  556. var self = this,
  557. settings = this._settings;
  558. if (!this._input || this._input.value === '') {
  559. return;
  560. }
  561. var file = fileFromPath(this._input.value);
  562. // user returned false to cancel upload
  563. if (false === settings.onSubmit.call(this, file, getExt(file))) {
  564. this._clearInput();
  565. return;
  566. }
  567. // sending request
  568. var iframe = this._createIframe();
  569. var form = this._createForm(iframe);
  570. // assuming following structure
  571. // div -> input type='file'
  572. removeNode(this._input.parentNode);
  573. removeClass(self._button, self._settings.hoverClass);
  574. form.appendChild(this._input);
  575. form.submit();
  576. // request set, clean up
  577. removeNode(form);
  578. form = null;
  579. removeNode(this._input);
  580. this._input = null;
  581. // Get response from iframe and fire onComplete event when ready
  582. this._getResponse(iframe, file);
  583. // get ready for next request
  584. this._createInput();
  585. }
  586. };
  587. })();