FileSaver(html5)

来自 https://github.com/eligrey/FileSaver.js

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/405376/816426/FileSaver%28html5%29.js

  1. // ==UserScript==
  2. // @name FileSaver(html5)
  3. // @namespace https://github.com/eligrey/FileSaver.js
  4. // @version 2.0.2
  5. // @description 来自 https://github.com/eligrey/FileSaver.js
  6. // ==/UserScript==
  7. (function (global, factory) {
  8. if (typeof define === "function" && define.amd) {
  9. define([], factory);
  10. } else if (typeof exports !== "undefined") {
  11. factory();
  12. } else {
  13. var mod = {
  14. exports: {}
  15. };
  16. factory();
  17. global.FileSaver = mod.exports;
  18. }
  19. })(this, function () {
  20. "use strict";
  21.  
  22. /*
  23. * FileSaver.js
  24. * A saveAs() FileSaver implementation.
  25. *
  26. * By Eli Grey, http://eligrey.com
  27. *
  28. * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
  29. * source : http://purl.eligrey.com/github/FileSaver.js
  30. */
  31. // The one and only way of getting global scope in all environments
  32. // https://stackoverflow.com/q/3277182/1008999
  33. var _global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : void 0;
  34.  
  35. function bom(blob, opts) {
  36. if (typeof opts === 'undefined') opts = {
  37. autoBom: false
  38. };else if (typeof opts !== 'object') {
  39. console.warn('Deprecated: Expected third argument to be a object');
  40. opts = {
  41. autoBom: !opts
  42. };
  43. } // prepend BOM for UTF-8 XML and text/* types (including HTML)
  44. // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
  45.  
  46. if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
  47. return new Blob([String.fromCharCode(0xFEFF), blob], {
  48. type: blob.type
  49. });
  50. }
  51.  
  52. return blob;
  53. }
  54.  
  55. function download(url, name, opts) {
  56. var xhr = new XMLHttpRequest();
  57. xhr.open('GET', url);
  58. xhr.responseType = 'blob';
  59.  
  60. xhr.onload = function () {
  61. saveAs(xhr.response, name, opts);
  62. };
  63.  
  64. xhr.onerror = function () {
  65. console.error('could not download file');
  66. };
  67.  
  68. xhr.send();
  69. }
  70.  
  71. function corsEnabled(url) {
  72. var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker
  73.  
  74. xhr.open('HEAD', url, false);
  75.  
  76. try {
  77. xhr.send();
  78. } catch (e) {}
  79.  
  80. return xhr.status >= 200 && xhr.status <= 299;
  81. } // `a.click()` doesn't work for all browsers (#465)
  82.  
  83.  
  84. function click(node) {
  85. try {
  86. node.dispatchEvent(new MouseEvent('click'));
  87. } catch (e) {
  88. var evt = document.createEvent('MouseEvents');
  89. evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
  90. node.dispatchEvent(evt);
  91. }
  92. }
  93.  
  94. var saveAs = _global.saveAs || ( // probably in some web worker
  95. typeof window !== 'object' || window !== _global ? function saveAs() {}
  96. /* noop */
  97. // Use download attribute first if possible (#193 Lumia mobile)
  98. : 'download' in HTMLAnchorElement.prototype ? function saveAs(blob, name, opts) {
  99. var URL = _global.URL || _global.webkitURL;
  100. var a = document.createElement('a');
  101. name = name || blob.name || 'download';
  102. a.download = name;
  103. a.rel = 'noopener'; // tabnabbing
  104. // TODO: detect chrome extensions & packaged apps
  105. // a.target = '_blank'
  106.  
  107. if (typeof blob === 'string') {
  108. // Support regular links
  109. a.href = blob;
  110.  
  111. if (a.origin !== location.origin) {
  112. corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank');
  113. } else {
  114. click(a);
  115. }
  116. } else {
  117. // Support blobs
  118. a.href = URL.createObjectURL(blob);
  119. setTimeout(function () {
  120. URL.revokeObjectURL(a.href);
  121. }, 4E4); // 40s
  122.  
  123. setTimeout(function () {
  124. click(a);
  125. }, 0);
  126. }
  127. } // Use msSaveOrOpenBlob as a second approach
  128. : 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) {
  129. name = name || blob.name || 'download';
  130.  
  131. if (typeof blob === 'string') {
  132. if (corsEnabled(blob)) {
  133. download(blob, name, opts);
  134. } else {
  135. var a = document.createElement('a');
  136. a.href = blob;
  137. a.target = '_blank';
  138. setTimeout(function () {
  139. click(a);
  140. });
  141. }
  142. } else {
  143. navigator.msSaveOrOpenBlob(bom(blob, opts), name);
  144. }
  145. } // Fallback to using FileReader and a popup
  146. : function saveAs(blob, name, opts, popup) {
  147. // Open a popup immediately do go around popup blocker
  148. // Mostly only available on user interaction and the fileReader is async so...
  149. popup = popup || open('', '_blank');
  150.  
  151. if (popup) {
  152. popup.document.title = popup.document.body.innerText = 'downloading...';
  153. }
  154.  
  155. if (typeof blob === 'string') return download(blob, name, opts);
  156. var force = blob.type === 'application/octet-stream';
  157.  
  158. var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
  159.  
  160. var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
  161.  
  162. if ((isChromeIOS || force && isSafari) && typeof FileReader === 'object') {
  163. // Safari doesn't allow downloading of blob URLs
  164. var reader = new FileReader();
  165.  
  166. reader.onloadend = function () {
  167. var url = reader.result;
  168. url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
  169. if (popup) popup.location.href = url;else location = url;
  170. popup = null; // reverse-tabnabbing #460
  171. };
  172.  
  173. reader.readAsDataURL(blob);
  174. } else {
  175. var URL = _global.URL || _global.webkitURL;
  176. var url = URL.createObjectURL(blob);
  177. if (popup) popup.location = url;else location.href = url;
  178. popup = null; // reverse-tabnabbing #460
  179.  
  180. setTimeout(function () {
  181. URL.revokeObjectURL(url);
  182. }, 4E4); // 40s
  183. }
  184. });
  185. _global.saveAs = saveAs.saveAs = saveAs;
  186.  
  187. if (typeof module !== 'undefined') {
  188. module.exports = saveAs;
  189. }
  190. });