-
Notifications
You must be signed in to change notification settings - Fork 80
/
zip.ts
120 lines (107 loc) · 3.25 KB
/
zip.ts
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
112
113
114
115
116
117
118
119
120
import { AsyncZipDeflate, Zip, ZipPassThrough } from "fflate";
import { saveAs } from "file-saver";
import streamSaver from "streamsaver";
import { mitmPageAvailability, streamSupport } from "../detect";
import { log } from "../log";
import { sleep } from "./misc";
export async function setStreamSaverSetting() {
const rawMitm = new URL(streamSaver.mitm);
const mitm = new URL("https://cors.bgme.me/");
mitm.pathname = rawMitm.origin + rawMitm.pathname;
streamSaver.mitm = mitm.href;
streamSaver.supported =
streamSupport() && (await mitmPageAvailability(mitm.href));
}
export class FflateZip {
public filename: string;
public stream: boolean;
private zcount = 0;
private count = 0;
private filenameList: string[] = [];
private zipOut: Blob = new Blob([], { type: "application/zip" });
private savedZip: Zip;
public constructor(
filename: string,
stream: boolean,
mimetype = "application/zip"
) {
log.info(
`[fflateZip] filename: ${filename}, stream: ${stream}, streamSaver.supported: ${streamSaver.supported}`
);
const self = this;
this.filename = filename;
if (streamSaver.supported) {
this.stream = stream;
} else {
this.stream = false;
}
let writer: WritableStreamDefaultWriter<Uint8Array>;
if (this.stream) {
const fileStream = streamSaver.createWriteStream(self.filename);
writer =
fileStream.getWriter() as WritableStreamDefaultWriter<Uint8Array>;
}
this.savedZip = new Zip((err, dat, final) => {
if (err) {
log.error(err);
log.trace(err);
if (self.stream) {
writer.abort();
}
throw err;
}
if (self.stream) {
writer.write(dat);
} else {
self.zipOut = new Blob([self.zipOut, dat], { type: mimetype });
}
if (final) {
if (self.stream) {
writer.close();
log.info("[fflateZip] ZIP生成完毕");
} else {
nonStream();
}
}
function nonStream() {
log.info("[fflateZip] ZIP生成完毕,文件大小:" + self.zipOut.size);
try {
saveAs(self.zipOut, self.filename);
self.zipOut = new Blob([], { type: "application/zip" });
} catch (error) {
log.error("[fflateZip]" + error);
log.trace(error);
}
}
});
}
public async file(filename: string, fileBlob: Blob, nocompress = false) {
if (this.filenameList.includes(filename)) {
log.warn(`filename ${filename} has existed on zip.`);
return;
}
this.filenameList.push(filename);
this.count++;
const buffer = await fileBlob.arrayBuffer();
const chunk = new Uint8Array(buffer);
if (fileBlob.type.includes("image/") || nocompress) {
const nonStreamingFile = new ZipPassThrough(filename);
this.savedZip.add(nonStreamingFile);
nonStreamingFile.push(chunk, true);
this.zcount++;
} else {
const nonStreamingFile = new AsyncZipDeflate(filename, {
level: 9,
});
this.savedZip.add(nonStreamingFile);
nonStreamingFile.push(chunk, true);
this.zcount++;
}
}
public async generateAsync() {
while (this.count !== this.zcount) {
await sleep(100);
}
this.savedZip.end();
}
}