我正在尝试使用 JavaScript 在浏览器中重建解压缩的 zip 文件的文件/文件夹结构。理想情况下,我希望将所有文件都放在FileList中 (就好像它们刚刚通过网页上传一样)或其他可迭代对象。例如,一个压缩文件夹包含
folder/file1
folder/file2
someotherfile
应该重构为一个 FileList/iterable 对象,其中每个项目对应于包中的一个文件(据我所知,没有办法在 JS 中保留文件夹结构)。
我在阅读 tar.gz 文件并使用pako和此问题底部的代码解压缩它方面非常成功。但是,pako 的结果是一个大的 ArrayBuffer(inflator.result
在下面的代码中),在尝试重建原始文件和文件夹时,我无法从中得出正面或反面。我遇到了以下问题:
- 我如何知道 ArrayBuffer 中一个文件的结束位置和另一个文件的开始位置?
- 如何确定当前文件的原始文件类型?
一旦我知道了这一点,我应该能够将 ArrayBuffer 数据转换为一个文件
File(segment, {type: filetype})
搜索网络也没有提供任何有用的信息。有没有人知道如何解决这个问题?
这是我用来解压缩 zipfile 的代码。
import pako from 'pako';
import isFunction from 'lodash/isFunction'
class FileStreamer {
constructor(file, chunkSize = 64 * 1024) {
this.file = file;
this.offset = 0;
this.chunkSize = chunkSize; // bytes
this.rewind();
}
rewind() {
this.offset = 0;
}
isEndOfFile() {
return this.offset >= this.getFileSize();
}
readBlock() {
const fileReader = new FileReader();
const blob = this.file.slice(this.offset, this.offset + this.chunkSize);
return new Promise((resolve, reject) => {
fileReader.onloadend = (event) => {
const target = (event.target);
if (target.error) {
return reject(target.error);
}
this.offset += target.result.byteLength;
resolve({
data: target.result,
progress: Math.min(this.offset / this.file.size, 1)
});
};
fileReader.readAsArrayBuffer(blob);
});
}
getFileSize() {
return this.file.size;
}
}
export async function decompress(zipfile, onProgress) {
const fs = new FileStreamer(zipfile);
const inflator = new pako.Inflate();
let block;
while (!fs.isEndOfFile()) {
block = await fs.readBlock();
inflator.push(block.data, fs.isEndOfFile());
if (inflator.err) {
throw inflator.err
}
if (isFunction(onProgress)) onProgress(block.progress)
}
return inflator.result;
}