Skip to content

Commit e15e5c8

Browse files
committed
Add FileSaver Lib Script
1 parent 230199c commit e15e5c8

File tree

2 files changed

+172
-0
lines changed

2 files changed

+172
-0
lines changed

index.html

+1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ <h3>Convert Youtube TimedText JSON to SRT</h3>
1414
<pre id="msg"></pre>
1515
</div>
1616
</body>
17+
<script src="lib/FileSaver.js"></script>
1718
<script src="main.js"></script>
1819
</html>

lib/FileSaver.js

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

0 commit comments

Comments
 (0)