-
-
Notifications
You must be signed in to change notification settings - Fork 421
/
saving-multiple-files.html
103 lines (90 loc) · 3.67 KB
/
saving-multiple-files.html
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
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="dark light">
<title>Saving multiple files as zip</title>
</head>
<body>
<button id="$start">Start</button>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ponyfill.min.js"></script>
<!--
includes blob.stream() polyfill
while Also making File constructor work in some browser that don't support it
-->
<script src="https://cdn.jsdelivr.net/gh/eligrey/Blob.js/Blob.js"></script>
<script src="../StreamSaver.js"></script>
<script src="zip-stream.js"></script>
<script>
$start.onclick = () => {
const fileStream = streamSaver.createWriteStream('archive.zip')
const file1 = new File(['file1 content'], 'streamsaver-zip-example/file1.txt')
// File Like object works too
const file2 = {
name: 'streamsaver-zip-example/file2.txt',
stream () {
// if you want to play it cool and use new api's
//
// const { readable, writable } = new TextEncoderStream()
// writable.write('file2 content')
// writable.close()
// return readable
return new ReadableStream({
start (ctrl) {
ctrl.enqueue(new TextEncoder().encode('file2 generated with readableStream'))
ctrl.close()
}
})
}
}
const blob = new Blob(['support blobs too'])
const file3 = {
name: 'streamsaver-zip-example/blob-example.txt',
stream: () => blob.stream()
}
// In a ideall world i would just have used a TransformStream
// where you would get `{ readable writable } = new TransformStream()`
// `readable` would be piped to streamsaver, and the writer would accept
// file-like object, but that made it dependent on TransformStream and WritableStream
// So i built ZIP-Stream simular to a ReadbleStream but you enqueue
// file-like objects meaning it should have at at the very least { name, stream() }
//
// it supports pull() too that gets called when it ask for more files.
//
// NOTE: My zip library can't generate zip's over 4gb and has no compresseion
// it was built solo for the purpus of saving multiple files in browser
//
// windows gets confused when file & folders starts with /
const readableZipStream = new ZIP({
start (ctrl) {
ctrl.enqueue(file1)
ctrl.enqueue(file2)
ctrl.enqueue(file3)
ctrl.enqueue({name: 'streamsaver-zip-example/empty folder', directory: true})
// ctrl.close()
},
async pull (ctrl) {
// Gets executed everytime zip.js asks for more data
const url = 'https://d8d913s460fub.cloudfront.net/videoserver/cat-test-video-320x240.mp4'
const res = await fetch(url)
const stream = () => res.body
const name = 'streamsaver-zip-example/cat.mp4'
ctrl.enqueue({ name, stream })
// if (done adding all files)
ctrl.close()
}
})
// more optimized
if (window.WritableStream && readableZipStream.pipeTo) {
return readableZipStream.pipeTo(fileStream).then(() => console.log('done writing'))
}
// less optimized
const writer = fileStream.getWriter()
const reader = readableZipStream.getReader()
const pump = () => reader.read()
.then(res => res.done ? writer.close() : writer.write(res.value).then(pump))
pump()
}
</script>
</body>
</html>