0. 更新时间
- 2023-12-11: 使用 zip.js 在浏览器中操作 zip
- 2023-12-12: 对比 JSZip 的使用并增加性能测试
1. 背景说明(由 chatgpt 生成)
文本文件的压缩技术在数据传输、存储和处理方面发挥着关键作用。压缩文本文件的过程通过各种算法和技术,将文件的大小减小到原始大小的一部分,这带来了诸多好处,特别是在上传文件、网络传输和存储方面。以下是关于针对文本文件做压缩的诸多好处的主要内容:
减少文件大小:压缩文本文件可以显著地减小文件的大小。通过使用压缩算法,文件的数据可以被有效地压缩,节省存储空间。
提高传输速度:较小的文件大小意味着更快的上传和下载速度。在网络传输过程中,压缩文件可以减少数据传输的时间,特别是对于带宽受限或网络速度较慢的情况下更为明显。
节省带宽和资源:在互联网传输数据时,压缩文本文件可以减少数据流量,降低带宽使用,同时也能减少服务器和客户端等系统资源的占用。
提高效率:压缩文本文件能够带来更高的效率,因为在处理大量文本数据时,更小的文件大小意味着更快的数据传输速度和更少的资源消耗。
节省成本:减少文件大小和提高传输效率可以降低存储成本和网络传输成本。这对于需要大规模存储和传输数据的组织和个人来说尤其重要。
方便存储和分享:压缩文本文件使得文件更易于存储和分享。更小的文件尺寸意味着更容易将文件传输到不同的位置或通过电子邮件等方式分享给其他人。
总体而言,压缩文本文件不仅可以节省空间和时间,还能提高数据传输的效率,降低成本,并提供更便捷的文件存储和分享方式。这使得文本文件压缩成为现代信息技术中不可或缺的一环
2. 技术选型
以上两个包支持浏览器和 nodejs, 但是建议选择第一个, 原因如下:
- 支持多核压缩
- 支持加密
- 协议友好
- zip.js: BSD-3-Clause license
- jszip: MIT license and GPLv3 license
- 性能好(参考: 4. 性能测试)
3. 代码实现
代码示例使用: vue + 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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
| <template> <h1>读取zip</h1> <input type="file" name="zipFile" /> <button type="button" @click="listZipFile">解压缩&读取</button> <button type="button" @click="listJSZipFile">解压缩&读取(jszip)</button>
<h1>创建zip</h1> <input type="file" name="sourceFile" multiple /> <button type="button" @click="createZip">创建压缩</button> <button type="button" @click="createJsZip">创建压缩(jszip)</button> </template>
<script setup lang="ts"> import { BlobReader, BlobWriter, ZipReader, ZipWriter } from "@zip.js/zip.js"; import JSZip from "jszip"; import { Buffer } from "buffer";
const listZipFile = async () => { const zipFileEle = document.querySelector<HTMLInputElement>( 'input[name="zipFile"]' ); if (!zipFileEle || !zipFileEle.files || zipFileEle.files!.length === 0) { console.error("no found zip"); return; } const start = Date.now(); const zipFile = zipFileEle.files[0]; const zipFileReader = new BlobReader(zipFile); const zipReader = new ZipReader(zipFileReader, { filenameEncoding: "utf8", commentEncoding: "utf8", }); const entries = await zipReader.getEntries(); for (const entry of entries) { if (entry.directory) { continue; } if (entry.filename.startsWith("__")) { continue; } if (entry.filename.startsWith(".")) { continue; } if (entry.filename.endsWith(".DS_Store")) { continue; } if (entry.filename.endsWith(".obj")) { const dataStream = new BlobWriter(); await entry.getData!(dataStream); const dateaBlob = await dataStream.getData(); const text = await dateaBlob.text(); console.log(`${entry.filename}的文件内容如下:`); console.log(text); } } await zipReader.close(); console.log(`耗时: ${((Date.now() - start) / 1000).toFixed()}/s`); };
const createZip = async () => { const start = Date.now(); const sourceFileEle = document.querySelector<HTMLInputElement>( 'input[name="sourceFile"]' ); if (!sourceFileEle || !sourceFileEle.files) { console.error("no found source files"); return; } const dataWriter = new BlobWriter(); const zipWriter = new ZipWriter(dataWriter, { level: 5 }); const createdFolders = new Map<string, boolean>(); for (const file of sourceFileEle.files) { if (file.name.endsWith(".obj") && !createdFolders.has("obj")) { await zipWriter.add("obj", undefined, { directory: true }); createdFolders.set("obj", true); await zipWriter.add(`obj/${file.name}`, file.stream()); } else { await zipWriter.add(file.name, file.stream()); } } await zipWriter.close(); const dataBlock = await dataWriter.getData();
const downloadEle = document.querySelector<HTMLAnchorElement>("#zipDownload") || document.createElement("a"); downloadEle.id = "zipDownload"; downloadEle.download = "objfile.zip"; downloadEle.href = URL.createObjectURL(dataBlock); downloadEle.textContent = "点击下载压缩文件"; sourceFileEle.parentNode?.insertBefore( downloadEle, downloadEle.nextSibling ); downloadEle.click(); console.log(`耗时: ${((Date.now() - start) / 1000).toFixed()}/s`); };
const createJsZip = async () => { const start = Date.now(); const sourceFileEle = document.querySelector<HTMLInputElement>( 'input[name="sourceFile"]' ); if (!sourceFileEle || !sourceFileEle.files) { console.error("no found source files"); return; } const zip = new JSZip(); for (const file of sourceFileEle.files) { const fileName = Buffer.from(file.name).toString("utf-8"); if (fileName.endsWith(".obj")) { await zip.folder("obj")?.file(fileName, file); } else { await zip.file(fileName, file); } } const zipBlob = await zip.generateAsync({ type: "blob", compression: "DEFLATE", compressionOptions: { level: 1, }, });
const downloadEle = document.querySelector<HTMLAnchorElement>("#zipDownload") || document.createElement("a"); downloadEle.id = "zipDownload"; downloadEle.download = "jszipobjfile.zip"; downloadEle.href = URL.createObjectURL(zipBlob); downloadEle.textContent = "点击下载压缩文件"; sourceFileEle.parentNode?.insertBefore( downloadEle, downloadEle.nextSibling ); downloadEle.click(); console.log(`耗时: ${((Date.now() - start) / 1000).toFixed()}/s`); };
const listJSZipFile = async () => { const zipFileEle = document.querySelector<HTMLInputElement>( 'input[name="zipFile"]' ); if (!zipFileEle || !zipFileEle.files || zipFileEle.files!.length === 0) { console.error("no found zip"); return; } const start = Date.now(); const file = zipFileEle.files[0]; const zip = new JSZip();
const entries = await zip.loadAsync(file); for (let filename in entries.files) { const entry = entries.files[filename]; if (entry.dir) { continue; } if (filename.startsWith("__")) { continue; } if (filename.startsWith(".")) { continue; } if (filename.endsWith(".DS_Store")) { continue; } if (filename.endsWith(".obj")) { const text = await entries.file(filename)?.async("string"); console.log(`${filename}的文件内容如下:`); console.log(text); } } console.log(`耗时: ${((Date.now() - start) / 1000).toFixed()}/s`); }; </script>
|
4. 性能测试
|
压缩 |
解压缩 |
zip.js |
耗时: 108s, 速率: 15MB/s |
耗时: 23s, 速率: 21MB/s |
jszip |
耗时: 511s, 速率: 3.2MB/s |
耗时: 176s, 速率: 3.3MB/s |
- 压缩目标: 120 个文件 1679MB
- 解压目标: 加压 zip 是对应压缩包压缩的结果, 解压并获取获取其中文件内容
总结: 从性能测试上看zip.js
虽然开源三年, star
没有开源十年多的jszip
多, 但是其技术优势比较领先, 后多核压缩的优势使得压缩效率非常高, 建议在浏览器环境下优先选择zip.js
5. 参考文档