forked from editdata/app.editdata.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsave-download-blob.js
111 lines (97 loc) · 3.83 KB
/
save-download-blob.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*global Blob, atob, confirm, location, FileReader*/
// download.js v4.0, by dandavis 2008-2015. [CCBY2] see http://danml.com/download.html for tests/usage
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
// v4 adds AMD/UMD, commonJS, and plain browser support
// https://github.com/rndme/download
module.exports = function download (data, strFileName, strMimeType) {
var self = window // this script is only for browsers anyway...
var u = 'application/octet-stream' // this default mime also triggers iframe downloads
var m = strMimeType || u
var x = data
var D = document
var a = D.createElement('a')
var z = function (a) { return String(a) }
var B = (self.Blob || self.MozBlob || self.WebKitBlob || z)
B = B.call ? B.bind(self) : Blob
var fn = strFileName || 'download'
var blob
var fr
if (String(this) === 'true') { // reverse arguments, allowing download.bind(true, 'text/xml', 'export.xml') to act as a callback
x = [x, m]
m = x[0]
x = x[1]
}
// go ahead and download dataURLs right away
if (String(x).match(/^data\:[\w+\-]+\/[\w+\-]+[,]/)) {
return navigator.msSaveBlob // IE10 can't do a[download], only Blobs:
? navigator.msSaveBlob(d2b(x), fn)
: saver(x) // everyone else can save dataURLs un-processed
} // end if dataURL passed?
blob = x instanceof B
? x
: new B([x], { type: m })
function d2b (u) {
var p = u.split(/[:,]/)
var t = p[1]
var dec = p[2] === 'base64' ? atob : decodeURIComponent
var bin = dec(p.pop())
var mx = bin.length
var i = 0
var uia = new Uint8Array(mx)
for (i; i < mx; ++i) uia[i] = bin.charCodeAt(i)
return new B([uia], {type: t})
}
function saver (url, winMode) {
if ('download' in a) { // html5 A[download]
a.href = url
a.setAttribute('download', fn)
a.innerHTML = 'downloading...'
D.body.appendChild(a)
setTimeout(function () {
a.click()
D.body.removeChild(a)
if (winMode === true) { setTimeout(function () { self.URL.revokeObjectURL(a.href) }, 250) }
}, 66)
return true
}
if (typeof safari !== 'undefined') { // handle non-a[download] safari as best we can:
url = 'data:' + url.replace(/^data:([\w\/\-\+]+)/, u)
if (!window.open(url)) { // popup blocked, offer direct download:
if (confirm('Displaying New Document\n\nUse Save As... to download, then click back to return to this page.')) { location.href = url }
}
return true
}
// do iframe dataURL download (old ch+FF):
var f = D.createElement('iframe')
D.body.appendChild(f)
if (!winMode) { // force a mime that will download:
url = 'data:' + url.replace(/^data:([\w\/\-\+]+)/, u)
}
f.src = url
setTimeout(function () { D.body.removeChild(f) }, 333)
} // end saver
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
return navigator.msSaveBlob(blob, fn)
}
if (self.URL) { // simple fast and modern way using Blob and URL:
saver(self.URL.createObjectURL(blob), true)
} else {
// handle non-Blob()+non-URL browsers:
if (typeof blob === 'string' || blob.constructor === z) {
try {
return saver('data:' + m + 'base64,' + self.btoa(blob))
} catch (y) {
return saver('data:' + m + ',' + encodeURIComponent(blob))
}
}
// Blob but not URL:
fr = new FileReader()
fr.onload = function (e) {
saver(this.result)
}
fr.readAsDataURL(blob)
}
return true
}