Sebastiankay commited on
Commit
f8332f9
·
verified ·
1 Parent(s): ac3fc65

Create demo-read-file.js

Browse files
Files changed (1) hide show
  1. demo-read-file.js +159 -0
demo-read-file.js ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global zip, document, URL, MouseEvent, AbortController, alert */
2
+
3
+ (() => {
4
+
5
+ if (typeof TransformStream == "undefined") {
6
+ const script = document.createElement("script");
7
+ script.src = "lib/web-streams-polyfill.min.js";
8
+ document.body.appendChild(script);
9
+ }
10
+
11
+ const model = (() => {
12
+
13
+ return {
14
+ getEntries(file, options) {
15
+ return (new zip.ZipReader(new zip.BlobReader(file))).getEntries(options);
16
+ },
17
+ async getURL(entry, options) {
18
+ return URL.createObjectURL(await entry.getData(new zip.BlobWriter(), options));
19
+ }
20
+ };
21
+
22
+ })();
23
+
24
+ (() => {
25
+
26
+ const appContainer = document.getElementById("container");
27
+ const fileInput = document.getElementById("file-input");
28
+ const encodingInput = document.getElementById("encoding-input");
29
+ const fileInputButton = document.getElementById("file-input-button");
30
+ const passwordInput = document.getElementById("password-input");
31
+ let fileList = document.getElementById("file-list");
32
+ let entries;
33
+ let selectedFile;
34
+ passwordInput.onchange = async () => fileList.querySelectorAll("a[download]").forEach(anchor => anchor.download = "");
35
+ fileInput.onchange = selectFile;
36
+ encodingInput.onchange = selectEncoding;
37
+ appContainer.onclick = downloadFile;
38
+ fileInputButton.onclick = () => fileInput.dispatchEvent(new MouseEvent("click"));
39
+
40
+ async function downloadFile(event) {
41
+ const target = event.target;
42
+ let href = target.getAttribute("href");
43
+ if (target.dataset.entryIndex !== undefined && !target.download && !href) {
44
+ target.removeAttribute("href");
45
+ event.preventDefault();
46
+ try {
47
+ await download(entries[Number(target.dataset.entryIndex)], target.parentElement.parentElement, target);
48
+ href = target.getAttribute("href");
49
+ } catch (error) {
50
+ alert(error);
51
+ }
52
+ target.setAttribute("href", href);
53
+ }
54
+ }
55
+
56
+ async function selectFile() {
57
+ try {
58
+ fileInputButton.disabled = true;
59
+ encodingInput.disabled = true;
60
+ selectedFile = fileInput.files[0];
61
+ await loadFiles();
62
+ } catch (error) {
63
+ alert(error);
64
+ } finally {
65
+ fileInputButton.disabled = false;
66
+ fileInput.value = "";
67
+ }
68
+ }
69
+
70
+ async function selectEncoding() {
71
+ try {
72
+ encodingInput.disabled = true;
73
+ fileInputButton.disabled = true;
74
+ await loadFiles(encodingInput.value);
75
+ } catch (error) {
76
+ alert(error);
77
+ } finally {
78
+ fileInputButton.disabled = false;
79
+ }
80
+ }
81
+
82
+ async function loadFiles(filenameEncoding) {
83
+ entries = await model.getEntries(selectedFile, { filenameEncoding });
84
+ if (entries && entries.length) {
85
+ fileList.classList.remove("empty");
86
+ const filenamesUTF8 = Boolean(!entries.find(entry => !entry.filenameUTF8));
87
+ const encrypted = Boolean(entries.find(entry => entry.encrypted));
88
+ encodingInput.value = filenamesUTF8 ? "utf-8" : filenameEncoding || "cp437";
89
+ encodingInput.disabled = filenamesUTF8;
90
+ passwordInput.value = "";
91
+ passwordInput.disabled = !encrypted;
92
+ refreshList();
93
+ }
94
+ }
95
+
96
+ function refreshList() {
97
+ const newFileList = fileList.cloneNode();
98
+ entries.forEach((entry, entryIndex) => {
99
+ const li = document.createElement("li");
100
+ const filenameContainer = document.createElement("span");
101
+ const filename = document.createElement("a");
102
+ filenameContainer.classList.add("filename-container");
103
+ li.appendChild(filenameContainer);
104
+ filename.classList.add("filename");
105
+ filename.dataset.entryIndex = entryIndex;
106
+ filename.textContent = filename.title = entry.filename;
107
+ filename.title = `${entry.filename}\n Last modification date: ${entry.lastModDate.toLocaleString()}`;
108
+ if (!entry.directory) {
109
+ filename.href = "";
110
+ filename.title += `\n Uncompressed size: ${entry.uncompressedSize.toLocaleString()} bytes`;
111
+ }
112
+ filenameContainer.appendChild(filename);
113
+ newFileList.appendChild(li);
114
+ });
115
+ fileList.replaceWith(newFileList);
116
+ fileList = newFileList;
117
+ }
118
+
119
+ async function download(entry, li, a) {
120
+ if (!li.classList.contains("busy")) {
121
+ const unzipProgress = document.createElement("progress");
122
+ li.appendChild(unzipProgress);
123
+ const controller = new AbortController();
124
+ const signal = controller.signal;
125
+ const abortButton = document.createElement("button");
126
+ abortButton.onclick = () => controller.abort();
127
+ abortButton.textContent = "✖";
128
+ abortButton.title = "Abort";
129
+ li.querySelector(".filename-container").appendChild(abortButton);
130
+ li.classList.add("busy");
131
+ li.onclick = event => event.preventDefault();
132
+ try {
133
+ const blobURL = await model.getURL(entry, {
134
+ password: passwordInput.value,
135
+ onprogress: (index, max) => {
136
+ unzipProgress.value = index;
137
+ unzipProgress.max = max;
138
+ },
139
+ signal
140
+ });
141
+ a.href = blobURL;
142
+ a.download = entry.filename;
143
+ const clickEvent = new MouseEvent("click");
144
+ a.dispatchEvent(clickEvent);
145
+ } catch (error) {
146
+ if (!signal.reason || signal.reason.code != error.code) {
147
+ throw error;
148
+ }
149
+ } finally {
150
+ li.classList.remove("busy");
151
+ unzipProgress.remove();
152
+ abortButton.remove();
153
+ }
154
+ }
155
+ }
156
+
157
+ })();
158
+
159
+ })();