1 /* FileSaver.js |
1 /* FileSaver.js |
2 * A saveAs() FileSaver implementation. |
2 * A saveAs() FileSaver implementation. |
3 * 1.1.20150716 |
3 * 1.1.20160328 |
4 * |
4 * |
5 * By Eli Grey, http://eligrey.com |
5 * By Eli Grey, http://eligrey.com |
6 * License: X11/MIT |
6 * License: MIT |
7 * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md |
7 * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md |
8 */ |
8 */ |
9 |
9 |
10 /*global self */ |
10 /*global self */ |
11 /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ |
11 /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ |
28 , can_use_save_link = "download" in save_link |
28 , can_use_save_link = "download" in save_link |
29 , click = function(node) { |
29 , click = function(node) { |
30 var event = new MouseEvent("click"); |
30 var event = new MouseEvent("click"); |
31 node.dispatchEvent(event); |
31 node.dispatchEvent(event); |
32 } |
32 } |
|
33 , is_safari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent) |
33 , webkit_req_fs = view.webkitRequestFileSystem |
34 , webkit_req_fs = view.webkitRequestFileSystem |
34 , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem |
35 , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem |
35 , throw_outside = function(ex) { |
36 , throw_outside = function(ex) { |
36 (view.setImmediate || view.setTimeout)(function() { |
37 (view.setImmediate || view.setTimeout)(function() { |
37 throw ex; |
38 throw ex; |
38 }, 0); |
39 }, 0); |
39 } |
40 } |
40 , force_saveable_type = "application/octet-stream" |
41 , force_saveable_type = "application/octet-stream" |
41 , fs_min_size = 0 |
42 , fs_min_size = 0 |
42 // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and |
43 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to |
43 // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 |
44 , arbitrary_revoke_timeout = 1000 * 40 // in ms |
44 // for the reasoning behind the timeout and revocation flow |
|
45 , arbitrary_revoke_timeout = 500 // in ms |
|
46 , revoke = function(file) { |
45 , revoke = function(file) { |
47 var revoker = function() { |
46 var revoker = function() { |
48 if (typeof file === "string") { // file is an object URL |
47 if (typeof file === "string") { // file is an object URL |
49 get_URL().revokeObjectURL(file); |
48 get_URL().revokeObjectURL(file); |
50 } else { // file is a File |
49 } else { // file is a File |
51 file.remove(); |
50 file.remove(); |
52 } |
51 } |
53 }; |
52 }; |
54 if (view.chrome) { |
53 /* // Take note W3C: |
55 revoker(); |
54 var |
56 } else { |
55 uri = typeof file === "string" ? file : file.toURL() |
57 setTimeout(revoker, arbitrary_revoke_timeout); |
56 , revoker = function(evt) { |
58 } |
57 // idealy DownloadFinishedEvent.data would be the URL requested |
|
58 if (evt.data === uri) { |
|
59 if (typeof file === "string") { // file is an object URL |
|
60 get_URL().revokeObjectURL(file); |
|
61 } else { // file is a File |
|
62 file.remove(); |
|
63 } |
|
64 } |
|
65 } |
|
66 ; |
|
67 view.addEventListener("downloadfinished", revoker); |
|
68 */ |
|
69 setTimeout(revoker, arbitrary_revoke_timeout); |
59 } |
70 } |
60 , dispatch = function(filesaver, event_types, event) { |
71 , dispatch = function(filesaver, event_types, event) { |
61 event_types = [].concat(event_types); |
72 event_types = [].concat(event_types); |
62 var i = event_types.length; |
73 var i = event_types.length; |
63 while (i--) { |
74 while (i--) { |
92 , dispatch_all = function() { |
103 , dispatch_all = function() { |
93 dispatch(filesaver, "writestart progress write writeend".split(" ")); |
104 dispatch(filesaver, "writestart progress write writeend".split(" ")); |
94 } |
105 } |
95 // on any filesys errors revert to saving with object URLs |
106 // on any filesys errors revert to saving with object URLs |
96 , fs_error = function() { |
107 , fs_error = function() { |
|
108 if (target_view && is_safari && typeof FileReader !== "undefined") { |
|
109 // Safari doesn't allow downloading of blob urls |
|
110 var reader = new FileReader(); |
|
111 reader.onloadend = function() { |
|
112 var base64Data = reader.result; |
|
113 target_view.location.href = "data:attachment/file" + base64Data.slice(base64Data.search(/[,;]/)); |
|
114 filesaver.readyState = filesaver.DONE; |
|
115 dispatch_all(); |
|
116 }; |
|
117 reader.readAsDataURL(blob); |
|
118 filesaver.readyState = filesaver.INIT; |
|
119 return; |
|
120 } |
97 // don't create more object URLs than needed |
121 // don't create more object URLs than needed |
98 if (blob_changed || !object_url) { |
122 if (blob_changed || !object_url) { |
99 object_url = get_URL().createObjectURL(blob); |
123 object_url = get_URL().createObjectURL(blob); |
100 } |
124 } |
101 if (target_view) { |
125 if (target_view) { |
102 target_view.location.href = object_url; |
126 target_view.location.href = object_url; |
103 } else { |
127 } else { |
104 var new_tab = view.open(object_url, "_blank"); |
128 var new_tab = view.open(object_url, "_blank"); |
105 if (new_tab == undefined && typeof safari !== "undefined") { |
129 if (new_tab === undefined && is_safari) { |
106 //Apple do not allow window.open, see http://bit.ly/1kZffRI |
130 //Apple do not allow window.open, see http://bit.ly/1kZffRI |
107 view.location.href = object_url |
131 view.location.href = object_url |
108 } |
132 } |
109 } |
133 } |
110 filesaver.readyState = filesaver.DONE; |
134 filesaver.readyState = filesaver.DONE; |
247 // while `this` is nsIContentFrameMessageManager |
271 // while `this` is nsIContentFrameMessageManager |
248 // with an attribute `content` that corresponds to the window |
272 // with an attribute `content` that corresponds to the window |
249 |
273 |
250 if (typeof module !== "undefined" && module.exports) { |
274 if (typeof module !== "undefined" && module.exports) { |
251 module.exports.saveAs = saveAs; |
275 module.exports.saveAs = saveAs; |
252 } else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) { |
276 } else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { |
253 define([], function() { |
277 define([], function() { |
254 return saveAs; |
278 return saveAs; |
255 }); |
279 }); |
256 } |
280 } |