save as for browser

fix for original version

Αυτός ο κώδικας δεν πρέπει να εγκατασταθεί άμεσα. Είναι μια βιβλιοθήκη για άλλους κώδικες που περιλαμβάνεται μέσω της οδηγίας meta // @require https://update.greatest.deepsurf.us/scripts/38382/250722/save%20as%20for%20browser.js

  1. var saveAs = saveAs
  2. // IE 10+ (native saveAs)
  3. || (typeof navigator !== "undefined" &&
  4. navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  5. // Everyone else
  6. || (function(view) {
  7. "use strict";
  8. // IE <10 is explicitly unsupported
  9. if (typeof navigator !== "undefined" &&
  10. /MSIE [1-9]\./.test(navigator.userAgent)) {
  11. return;
  12. }
  13. var
  14. doc = view.document
  15. // only get URL when necessary in case Blob.js hasn't overridden it yet
  16. , get_URL = function() {
  17. return view.URL || view.webkitURL || view;
  18. }
  19. , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
  20. , can_use_save_link = "download" in save_link
  21. , click = function(node) {
  22. var event = new MouseEvent("click");
  23. node.dispatchEvent(event);
  24. }
  25. , webkit_req_fs = view.webkitRequestFileSystem
  26. , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
  27. , throw_outside = function(ex) {
  28. (view.setImmediate || view.setTimeout)(function() {
  29. throw ex;
  30. }, 0);
  31. }
  32. , force_saveable_type = "application/octet-stream"
  33. , fs_min_size = 0
  34. , deletion_queue = []
  35. , process_deletion_queue = function() {
  36. var i = deletion_queue.length;
  37. while (i--) {
  38. var file = deletion_queue[i];
  39. if (typeof file === "string") { // file is an object URL
  40. get_URL().revokeObjectURL(file);
  41. } else { // file is a File
  42. file.remove();
  43. }
  44. }
  45. deletion_queue.length = 0; // clear queue
  46. }
  47. , dispatch = function(filesaver, event_types, event) {
  48. event_types = [].concat(event_types);
  49. var i = event_types.length;
  50. while (i--) {
  51. var listener = filesaver["on" + event_types[i]];
  52. if (typeof listener === "function") {
  53. try {
  54. listener.call(filesaver, event || filesaver);
  55. } catch (ex) {
  56. throw_outside(ex);
  57. }
  58. }
  59. }
  60. }
  61. , FileSaver = function(blob, name) {
  62. // First try a.download, then web filesystem, then object URLs
  63. var
  64. filesaver = this
  65. , type = blob.type
  66. , blob_changed = false
  67. , object_url
  68. , target_view
  69. , get_object_url = function() {
  70. var object_url = get_URL().createObjectURL(blob);
  71. deletion_queue.push(object_url);
  72. return object_url;
  73. }
  74. , dispatch_all = function() {
  75. dispatch(filesaver, "writestart progress write writeend".split(" "));
  76. }
  77. // on any filesys errors revert to saving with object URLs
  78. , fs_error = function() {
  79. // don't create more object URLs than needed
  80. if (blob_changed || !object_url) {
  81. object_url = get_object_url(blob);
  82. }
  83. if (target_view) {
  84. target_view.location.href = object_url;
  85. } else {
  86. window.open(object_url, "_blank");
  87. }
  88. filesaver.readyState = filesaver.DONE;
  89. dispatch_all();
  90. }
  91. , abortable = function(func) {
  92. return function() {
  93. if (filesaver.readyState !== filesaver.DONE) {
  94. return func.apply(this, arguments);
  95. }
  96. };
  97. }
  98. , create_if_not_found = {create: true, exclusive: false}
  99. , slice
  100. ;
  101. filesaver.readyState = filesaver.INIT;
  102. if (!name) {
  103. name = "download";
  104. }
  105. if (can_use_save_link) {
  106. object_url = get_object_url(blob);
  107. save_link.href = object_url;
  108. save_link.download = name;
  109. click(save_link);
  110. filesaver.readyState = filesaver.DONE;
  111. dispatch_all();
  112. return;
  113. }
  114. // Object and web filesystem URLs have a problem saving in Google Chrome when
  115. // viewed in a tab, so I force save with application/octet-stream
  116. // http://code.google.com/p/chromium/issues/detail?id=91158
  117. if (view.chrome && type && type !== force_saveable_type) {
  118. slice = blob.slice || blob.webkitSlice;
  119. blob = slice.call(blob, 0, blob.size, force_saveable_type);
  120. blob_changed = true;
  121. }
  122. // Since I can't be sure that the guessed media type will trigger a download
  123. // in WebKit, I append .download to the filename.
  124. // https://bugs.webkit.org/show_bug.cgi?id=65440
  125. if (webkit_req_fs && name !== "download") {
  126. name += ".download";
  127. }
  128. if (type === force_saveable_type || webkit_req_fs) {
  129. target_view = view;
  130. }
  131. if (!req_fs) {
  132. fs_error();
  133. return;
  134. }
  135. fs_min_size += blob.size;
  136. req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
  137. fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
  138. var save = function() {
  139. dir.getFile(name, create_if_not_found, abortable(function(file) {
  140. file.createWriter(abortable(function(writer) {
  141. writer.onwriteend = function(event) {
  142. target_view.location.href = file.toURL();
  143. deletion_queue.push(file);
  144. filesaver.readyState = filesaver.DONE;
  145. dispatch(filesaver, "writeend", event);
  146. };
  147. writer.onerror = function() {
  148. var error = writer.error;
  149. if (error.code !== error.ABORT_ERR) {
  150. fs_error();
  151. }
  152. };
  153. "writestart progress write abort".split(" ").forEach(function(event) {
  154. writer["on" + event] = filesaver["on" + event];
  155. });
  156. writer.write(blob);
  157. filesaver.abort = function() {
  158. writer.abort();
  159. filesaver.readyState = filesaver.DONE;
  160. };
  161. filesaver.readyState = filesaver.WRITING;
  162. }), fs_error);
  163. }), fs_error);
  164. };
  165. dir.getFile(name, {create: false}, abortable(function(file) {
  166. // delete file if it already exists
  167. file.remove();
  168. save();
  169. }), abortable(function(ex) {
  170. if (ex.code === ex.NOT_FOUND_ERR) {
  171. save();
  172. } else {
  173. fs_error();
  174. }
  175. }));
  176. }), fs_error);
  177. }), fs_error);
  178. }
  179. , FS_proto = FileSaver.prototype
  180. , saveAs = function(blob, name) {
  181. return new FileSaver(blob, name);
  182. }
  183. ;
  184. FS_proto.abort = function() {
  185. var filesaver = this;
  186. filesaver.readyState = filesaver.DONE;
  187. dispatch(filesaver, "abort");
  188. };
  189. FS_proto.readyState = FS_proto.INIT = 0;
  190. FS_proto.WRITING = 1;
  191. FS_proto.DONE = 2;
  192.  
  193. FS_proto.error =
  194. FS_proto.onwritestart =
  195. FS_proto.onprogress =
  196. FS_proto.onwrite =
  197. FS_proto.onabort =
  198. FS_proto.onerror =
  199. FS_proto.onwriteend =
  200. null;
  201.  
  202. view.addEventListener("unload", process_deletion_queue, false);
  203. saveAs.unload = function() {
  204. process_deletion_queue();
  205. view.removeEventListener("unload", process_deletion_queue, false);
  206. };
  207. return saveAs;
  208. }(
  209. typeof self !== "undefined" && self
  210. || typeof window !== "undefined" && window
  211. || this.content
  212. ));
  213. // `self` is undefined in Firefox for Android content script context
  214. // while `this` is nsIContentFrameMessageManager
  215. // with an attribute `content` that corresponds to the window
  216.  
  217. if (typeof module !== "undefined" && module !== null) {
  218. module.exports = saveAs;
  219. } else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
  220. define([], function() {
  221. return saveAs;
  222. });
  223. }