1
+ /* FileSaver.js
2
+ * A saveAs() FileSaver implementation.
3
+ * 1.3.2
4
+ * 2016-06-16 18:25:19
5
+ *
6
+ * By Eli Grey, http://eligrey.com
7
+ * License: MIT
8
+ * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
9
+ */
10
+
11
+ /*global self */
12
+ /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
13
+
14
+ /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
15
+
16
+ var saveAs = saveAs || ( function ( view ) {
17
+ "use strict" ;
18
+ // IE <10 is explicitly unsupported
19
+ if ( typeof view === "undefined" || typeof navigator !== "undefined" && / M S I E [ 1 - 9 ] \. / . test ( navigator . userAgent ) ) {
20
+ return ;
21
+ }
22
+ var
23
+ doc = view . document
24
+ // only get URL when necessary in case Blob.js hasn't overridden it yet
25
+ , get_URL = function ( ) {
26
+ return view . URL || view . webkitURL || view ;
27
+ }
28
+ , save_link = doc . createElementNS ( "http://www.w3.org/1999/xhtml" , "a" )
29
+ , can_use_save_link = "download" in save_link
30
+ , click = function ( node ) {
31
+ var event = new MouseEvent ( "click" ) ;
32
+ node . dispatchEvent ( event ) ;
33
+ }
34
+ , is_safari = / c o n s t r u c t o r / i. test ( view . HTMLElement ) || view . safari
35
+ , is_chrome_ios = / C r i O S \/ [ \d ] + / . test ( navigator . userAgent )
36
+ , throw_outside = function ( ex ) {
37
+ ( view . setImmediate || view . setTimeout ) ( function ( ) {
38
+ throw ex ;
39
+ } , 0 ) ;
40
+ }
41
+ , force_saveable_type = "application/octet-stream"
42
+ // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
43
+ , arbitrary_revoke_timeout = 1000 * 40 // in ms
44
+ , revoke = function ( file ) {
45
+ var revoker = function ( ) {
46
+ if ( typeof file === "string" ) { // file is an object URL
47
+ get_URL ( ) . revokeObjectURL ( file ) ;
48
+ } else { // file is a File
49
+ file . remove ( ) ;
50
+ }
51
+ } ;
52
+ setTimeout ( revoker , arbitrary_revoke_timeout ) ;
53
+ }
54
+ , dispatch = function ( filesaver , event_types , event ) {
55
+ event_types = [ ] . concat ( event_types ) ;
56
+ var i = event_types . length ;
57
+ while ( i -- ) {
58
+ var listener = filesaver [ "on" + event_types [ i ] ] ;
59
+ if ( typeof listener === "function" ) {
60
+ try {
61
+ listener . call ( filesaver , event || filesaver ) ;
62
+ } catch ( ex ) {
63
+ throw_outside ( ex ) ;
64
+ }
65
+ }
66
+ }
67
+ }
68
+ , auto_bom = function ( blob ) {
69
+ // prepend BOM for UTF-8 XML and text/* types (including HTML)
70
+ // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
71
+ if ( / ^ \s * (?: t e x t \/ \S * | a p p l i c a t i o n \/ x m l | \S * \/ \S * \+ x m l ) \s * ; .* c h a r s e t \s * = \s * u t f - 8 / i. test ( blob . type ) ) {
72
+ return new Blob ( [ String . fromCharCode ( 0xFEFF ) , blob ] , { type : blob . type } ) ;
73
+ }
74
+ return blob ;
75
+ }
76
+ , FileSaver = function ( blob , name , no_auto_bom ) {
77
+ if ( ! no_auto_bom ) {
78
+ blob = auto_bom ( blob ) ;
79
+ }
80
+ // First try a.download, then web filesystem, then object URLs
81
+ var
82
+ filesaver = this
83
+ , type = blob . type
84
+ , force = type === force_saveable_type
85
+ , object_url
86
+ , dispatch_all = function ( ) {
87
+ dispatch ( filesaver , "writestart progress write writeend" . split ( " " ) ) ;
88
+ }
89
+ // on any filesys errors revert to saving with object URLs
90
+ , fs_error = function ( ) {
91
+ if ( ( is_chrome_ios || ( force && is_safari ) ) && view . FileReader ) {
92
+ // Safari doesn't allow downloading of blob urls
93
+ var reader = new FileReader ( ) ;
94
+ reader . onloadend = function ( ) {
95
+ var url = is_chrome_ios ? reader . result : reader . result . replace ( / ^ d a t a : [ ^ ; ] * ; / , 'data:attachment/file;' ) ;
96
+ var popup = view . open ( url , '_blank' ) ;
97
+ if ( ! popup ) view . location . href = url ;
98
+ url = undefined ; // release reference before dispatching
99
+ filesaver . readyState = filesaver . DONE ;
100
+ dispatch_all ( ) ;
101
+ } ;
102
+ reader . readAsDataURL ( blob ) ;
103
+ filesaver . readyState = filesaver . INIT ;
104
+ return ;
105
+ }
106
+ // don't create more object URLs than needed
107
+ if ( ! object_url ) {
108
+ object_url = get_URL ( ) . createObjectURL ( blob ) ;
109
+ }
110
+ if ( force ) {
111
+ view . location . href = object_url ;
112
+ } else {
113
+ var opened = view . open ( object_url , "_blank" ) ;
114
+ if ( ! opened ) {
115
+ // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
116
+ view . location . href = object_url ;
117
+ }
118
+ }
119
+ filesaver . readyState = filesaver . DONE ;
120
+ dispatch_all ( ) ;
121
+ revoke ( object_url ) ;
122
+ }
123
+ ;
124
+ filesaver . readyState = filesaver . INIT ;
125
+
126
+ if ( can_use_save_link ) {
127
+ object_url = get_URL ( ) . createObjectURL ( blob ) ;
128
+ setTimeout ( function ( ) {
129
+ save_link . href = object_url ;
130
+ save_link . download = name ;
131
+ click ( save_link ) ;
132
+ dispatch_all ( ) ;
133
+ revoke ( object_url ) ;
134
+ filesaver . readyState = filesaver . DONE ;
135
+ } ) ;
136
+ return ;
137
+ }
138
+
139
+ fs_error ( ) ;
140
+ }
141
+ , FS_proto = FileSaver . prototype
142
+ , saveAs = function ( blob , name , no_auto_bom ) {
143
+ if ( no_auto_bom === undefined ) no_auto_bom = true ;
144
+ return new FileSaver ( blob , name || blob . name || "download" , no_auto_bom ) ;
145
+ }
146
+ ;
147
+ // IE 10+ (native saveAs)
148
+ if ( typeof navigator !== "undefined" && navigator . msSaveOrOpenBlob ) {
149
+ return function ( blob , name , no_auto_bom ) {
150
+ name = name || blob . name || "download" ;
151
+
152
+ if ( ! no_auto_bom ) {
153
+ blob = auto_bom ( blob ) ;
154
+ }
155
+ return navigator . msSaveOrOpenBlob ( blob , name ) ;
156
+ } ;
157
+ }
158
+
159
+ FS_proto . abort = function ( ) { } ;
160
+ FS_proto . readyState = FS_proto . INIT = 0 ;
161
+ FS_proto . WRITING = 1 ;
162
+ FS_proto . DONE = 2 ;
163
+
164
+ FS_proto . error =
165
+ FS_proto . onwritestart =
166
+ FS_proto . onprogress =
167
+ FS_proto . onwrite =
168
+ FS_proto . onabort =
169
+ FS_proto . onerror =
170
+ FS_proto . onwriteend =
171
+ null ;
172
+
173
+ return saveAs ;
174
+ } (
175
+ typeof self !== "undefined" && self
176
+ || typeof window !== "undefined" && window
177
+ || this . content
178
+ ) ) ;
179
+ // `self` is undefined in Firefox for Android content script context
180
+ // while `this` is nsIContentFrameMessageManager
181
+ // with an attribute `content` that corresponds to the window
182
+
183
+ if ( typeof module !== "undefined" && module . exports ) {
184
+ module . exports . saveAs = saveAs ;
185
+ } else if ( ( typeof define !== "undefined" && define !== null ) && ( define . amd !== null ) ) {
186
+ define ( "FileSaver.js" , function ( ) {
187
+ return saveAs ;
188
+ } ) ;
189
+ }
0 commit comments