HTML5.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.form.uploader.plugins.HTML5"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.form.uploader.plugins.HTML5"] = true;
  8. dojo.provide("dojox.form.uploader.plugins.HTML5");
  9. dojo.declare("dojox.form.uploader.plugins.HTML5", [], {
  10. //
  11. // Version: 1.6
  12. //
  13. // summary:
  14. // A plugin for dojox.form.Uploader that adds HTML5 multiple-file upload capabilities and
  15. // progress events.
  16. //
  17. // description:
  18. // Add this plugin to have HTML5 capabilities in the Uploader. Note that it does not add
  19. // these capabilities to browsers that don't support them. For IE or older browsers, add
  20. // additional plugins: IFrame or Flash.
  21. //
  22. errMsg:"Error uploading files. Try checking permissions",
  23. // Overwrites "form" and could possibly be overwritten again by iframe or flash plugin.
  24. uploadType:"html5",
  25. postCreate: function(){
  26. this.connectForm();
  27. this.inherited(arguments);
  28. if(this.uploadOnSelect){
  29. this.connect(this, "onChange", "upload");
  30. }
  31. },
  32. /*************************
  33. * Public Methods *
  34. *************************/
  35. upload: function(/*Object ? */formData){
  36. // summary:
  37. // See: dojox.form.Uploader.upload
  38. //
  39. this.onBegin(this.getFileList());
  40. if(this.supports("FormData")){
  41. this.uploadWithFormData(formData);
  42. }else if(this.supports("sendAsBinary")){
  43. this.sendAsBinary(formData);
  44. }
  45. },
  46. submit: function(/* form Node ? */form){
  47. // summary:
  48. // See: dojox.form.Uploader.submit
  49. //
  50. form = !!form ? form.tagName ? form : this.getForm() : this.getForm();
  51. var data = dojo.formToObject(form);
  52. console.log("form data:", data);
  53. this.upload(data);
  54. },
  55. sendAsBinary: function(/* Object */data){
  56. // summary:
  57. // Used primarily in FF < 4.0. Sends files and form object as binary data, written to
  58. // still enable use of $_FILES in PHP (or equivalent).
  59. // tags:
  60. // private
  61. //
  62. if(!this.getUrl()){
  63. console.error("No upload url found.", this); return;
  64. }
  65. // The date/number doesn't matter but amount of dashes do. The actual boundary
  66. // will have two more dashes than this one which is used in the header.
  67. var boundary = "---------------------------" + (new Date).getTime();
  68. var xhr = this.createXhr();
  69. xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
  70. // finally send the request as binary data
  71. // still accessed as $_FILES
  72. var msg = this._buildRequestBody(data, boundary);
  73. if(!msg){
  74. this.onError(this.errMsg);
  75. }else{
  76. xhr.sendAsBinary(msg);
  77. }
  78. },
  79. uploadWithFormData: function(/* Object */data){
  80. // summary
  81. // Used with WebKit and Firefox 4+
  82. // Upload files using the much friendlier FormData browser object.
  83. // tags:
  84. // private
  85. //
  86. if(!this.getUrl()){
  87. console.error("No upload url found.", this); return;
  88. }
  89. var fd = new FormData();
  90. dojo.forEach(this.inputNode.files, function(f, i){
  91. fd.append(this.name+"s[]", f);
  92. }, this);
  93. if(data){
  94. for(var nm in data){
  95. fd.append(nm, data[nm]);
  96. }
  97. }
  98. var xhr = this.createXhr();
  99. xhr.send(fd);
  100. },
  101. _xhrProgress: function(evt){
  102. if(evt.lengthComputable){
  103. var o = {
  104. bytesLoaded:evt.loaded,
  105. bytesTotal:evt.total,
  106. type:evt.type,
  107. timeStamp:evt.timeStamp
  108. };
  109. if(evt.type == "load"){
  110. // 100%
  111. o.percent = "100%",
  112. o.decimal = 1;
  113. }else{
  114. o.decimal = evt.loaded / evt.total;
  115. o.percent = Math.ceil((evt.loaded / evt.total)*100)+"%";
  116. }
  117. this.onProgress(o);
  118. }
  119. },
  120. createXhr: function(){
  121. var xhr = new XMLHttpRequest();
  122. var timer;
  123. xhr.upload.addEventListener("progress", dojo.hitch(this, "_xhrProgress"), false);
  124. xhr.addEventListener("load", dojo.hitch(this, "_xhrProgress"), false);
  125. xhr.addEventListener("error", dojo.hitch(this, function(evt){
  126. this.onError(evt);
  127. clearInterval(timer);
  128. }), false);
  129. xhr.addEventListener("abort", dojo.hitch(this, function(evt){
  130. this.onAbort(evt);
  131. clearInterval(timer);
  132. }), false);
  133. xhr.onreadystatechange = dojo.hitch(this, function() {
  134. if (xhr.readyState === 4) {
  135. console.info("COMPLETE")
  136. clearInterval(timer);
  137. this.onComplete(dojo.eval(xhr.responseText));
  138. }
  139. });
  140. xhr.open("POST", this.getUrl());
  141. timer = setInterval(dojo.hitch(this, function(){
  142. try{
  143. if(typeof(xhr.statusText)){} // accessing this error throws an error. Awesomeness.
  144. }catch(e){
  145. //this.onError("Error uploading file."); // not always an error.
  146. clearInterval(timer);
  147. }
  148. }),250);
  149. return xhr;
  150. },
  151. _buildRequestBody : function(data, boundary) {
  152. var EOL = "\r\n";
  153. var part = "";
  154. boundary = "--" + boundary;
  155. var filesInError = [];
  156. dojo.forEach(this.inputNode.files, function(f, i){
  157. var fieldName = this.name+"s[]";//+i;
  158. var fileName = this.inputNode.files[i].fileName;
  159. var binary;
  160. try{
  161. binary = this.inputNode.files[i].getAsBinary() + EOL;
  162. part += boundary + EOL;
  163. part += 'Content-Disposition: form-data; ';
  164. part += 'name="' + fieldName + '"; ';
  165. part += 'filename="'+ fileName + '"' + EOL;
  166. part += "Content-Type: " + this.getMimeType() + EOL + EOL;
  167. part += binary;
  168. }catch(e){
  169. filesInError.push({index:i, name:fileName});
  170. }
  171. }, this);
  172. if(filesInError.length){
  173. if(filesInError.length >= this.inputNode.files.length){
  174. // all files were bad. Nothing to upload.
  175. this.onError({
  176. message:this.errMsg,
  177. filesInError:filesInError
  178. });
  179. part = false;
  180. }
  181. }
  182. if(!part) return false;
  183. if(data){
  184. for(var nm in data){
  185. part += boundary + EOL;
  186. part += 'Content-Disposition: form-data; ';
  187. part += 'name="' + nm + '"' + EOL + EOL;
  188. part += data[nm] + EOL;
  189. }
  190. }
  191. part += boundary + "--" + EOL;
  192. return part;
  193. }
  194. });
  195. dojox.form.addUploaderPlugin(dojox.form.uploader.plugins.HTML5);
  196. }