js读取zip文件

简介

因为最近的一些业务上的需求,希望将项目中的一部分文件压缩(其实服务器开启gzip就行了,但是不知道为啥这个gzip时不时的抽风,只好作罢使用zip.js),这些文件内容重复率高,体积大,有些文件压缩前30m压缩后只有300k,平时经常使用的json文件,压缩前987k压缩后也只有280k。

zipjs可以做到读取解压缩的内容和压缩文件内容,这里只用到了解压缩的部分,直接从url中读取,有些文件内容本身比较小,或者图片文件本身压缩比就比较高,不适合去压缩,那么这部分读不到的内容就会使用fetch读取源文件内容。

读取zip文件路径的方式比较简单粗暴,直接将路径后缀换成zip,而读取文件的部分是asyc函数,方便项目中灵活使用

特征

除了对zip.js封装外,还支持处理管理,只需要再创建时注入manager即可,manager中有onStart,onError,onLoad,onProgress四个事件即可。

源代码

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
import * as zip from "@zip.js/zip.js";

/**
* ZIPLoader
* https://www.msy.plus/2021/12/15/js-zipjs/
* @version 0.0.1
* @author 刘九江
* @license AGPL
*/
class ZIPLoader{

constructor(manager){
this.manager = manager;
}

getReader(file) {
return (new zip.ZipReader(new zip.HttpReader(file)));
}

/**
*
* @param url
* @param {'Blob'| 'Text' | 'Uint8Array' | 'Data64URI' } type
* @return {Promise<*>}
*/
async load(url,type) {
let text;
this.manager.onStart(url);
const urlSplit = url.split(".");
urlSplit[urlSplit.length-1] = "zip";
const finalUrl = urlSplit.join(".");
try {
const reader = this.getReader(finalUrl);

const entries = await reader.getEntries({
useWebWorkers:true,
onprogress:(index,max)=>{
this.manager.onProgress(url,index,max);
// console.log("getEntries",index,max);
}
});

if (entries && entries.length) {
text = await entries[0].getData(
new zip[type +"Writer"](),
{
useWebWorkers:true,
onporgress:(index,max)=>{
console.log(index,max);
}
}
);
}

await reader.close();
}catch (e) {
this.manager.onError(e);
console.error("[zip file error]:"+finalUrl,e);
}
return text;
}

async loadTextFile(url){
let text = await this.load(url,"Text");

if(!text){
const res = await fetch(url);
text = await res.text();
}
this.manager.onLoad(url);

return text;
}

async loadBlobFile(url){
let text = await this.load(url,"Blob");

if(!text){
const res = await fetch(url);
text = await res.blob();
}
this.manager.onLoad(url);

return text;
}
async loadUint8Array(url){
let text = await this.load(url,"Uint8Array");

if(!text){
const res = await fetch(url);
text = await res.arrayBuffer();
}
this.manager.onLoad(url);

return text;
}
}

export {ZIPLoader};