2

我正在编写软件,其中包括使用 Dropbox API 下载 zip 存档,然后使用 yauzl 解压缩该存档。

从数据库存储和下载文件的方式通常以嵌套文件夹结尾,我需要保持这种方式。

但是,我的 yauzl 实现无法在保持嵌套文件夹结构的同时解压缩,如果存档中有嵌套文件夹,它根本不会解压缩。

这是我的解压缩函数,这是默认的 yauzl 示例,最后添加了本地文件写入。

const unzip = () => {
    let zipPath = "pathToFile.zip"
    let extractPath = "pathToExtractLocation"

        yauzl.open(zipPath, {lazyEntries: true}, function(err, zipfile) {
            if (err) throw err;
            zipfile.readEntry();
            zipfile.on("entry", function(entry) {
            if (/\/$/.test(entry.fileName)) {
                // Directory file names end with '/'.
                // Note that entries for directories themselves are optional.
                // An entry's fileName implicitly requires its parent directories to exist.
                zipfile.readEntry();
            } else {
                // file entry
                zipfile.openReadStream(entry, function(err, readStream) {
                if (err) throw err;
                readStream.on("end", function() {
                    zipfile.readEntry();
                });
                const writer = fs.createWriteStream(path.join(extractPath, entry.fileName));
                readStream.pipe(writer);
                });
            }
            });
        });
}

删除if (/\/$/.test(entry.fileName))检查会将顶级文件夹视为文件,将其提取为没有文件扩展名和 0kb 大小。我想要它做的是提取包含子文件夹的存档(至少深度为 2,注意 zip 轰炸的风险)。

这可能使用yauzl吗?

4

1 回答 1

0

代码需要在解压路径创建目录树。您可以使用fs.mkdirwithrecursive选项来确保在提取目录之前存在目录。

if (/\/$/.test(entry.fileName)) {
  // Directory file names end with '/'.
  // Note that entries for directories themselves are optional.
  // An entry's fileName implicitly requires its parent directories to exist.
  zipfile.readEntry();
} else {
  // file entry
  fs.mkdir(
    path.join(extractPath, path.dirname(entry.fileName)),
    { recursive: true },
    (err) => {
      if (err) throw err;
      zipfile.openReadStream(entry, function (err, readStream) {
        if (err) throw err;
        readStream.on("end", function () {
          zipfile.readEntry();
        });
        const writer = fs.createWriteStream(
          path.join(extractPath, entry.fileName)
        );
        readStream.pipe(writer);
      });
    }
  );
}
于 2022-02-07T16:04:02.153 回答