使用JSZip创建、读取和修改Zip文件

6,330 阅读6分钟

如果你不熟悉FileSaver.js的使用,可以参考官方文档进行学习:github.com/eligrey/Fil…

下面我们将逐步介绍如何使用JSZip创建、读取和修改Zip文件。

创建Zip文件

使用JSZip创建Zip文件非常简单。我们只需要创建一个Zip实例,并向其中添加文件即可。

// 创建一个Zip实例
var zip = new JSZip();

// 向Zip中添加文件
zip.file("hello.txt", "Hello World\n");
zip.file("foo/bar.txt", "Bar\n");

在上面的代码中,我们首先创建了一个Zip实例,并向其中添加了两个文件(分别位于根目录和子目录下)。其中,file()方法用于向Zip中添加文件,它接受两个参数:文件名和文件内容。

除了使用字符串作为文件内容外,我们还可以使用ArrayBuffer或Uint8Array等类型的数据作为文件内容。例如:

// 创建一个Zip实例
var zip = new JSZip();

// 创建一个Uint8Array
var data = new Uint8Array([1, 2, 3]);

// 向Zip中添加文件
zip.file("data.bin", data);

在上面的代码中,我们创建了一个Uint8Array,并将其作为二进制数据添加到Zip中。

当我们向Zip中添加文件时,JSZip会自动根据文件内容计算出CRC32和压缩方式。如果文件内容不是文本类型,JSZip会默认使用DEFLATE算法进行压缩,以减小文件大小。如果需要修改默认的压缩方式,可以通过参数进行设置。例如:

// 创建一个Zip实例
var zip = new JSZip();

// 向Zip中添加文件(使用STORE算法)
zip.file("hello.txt", "Hello World\n", {compression: "STORE"});

在上面的代码中,我们向Zip中添加了一个文件,并指定使用STROE算法进行压缩。STORE算法不会对文件进行压缩,因此可以保留文件原本的大小。

生成Zip文件

当我们向Zip中添加文件后,就可以将其打包成一个Zip文件并下载了。使用JSZip,我们可以将Zip文件打包成Blob对象或Base64字符串,并通过浏览器提供的函数进行下载。

打包成Blob对象

要将Zip打包成Blob对象,我们可以使用generateAsync()方法。

// 创建一个Zip实例
var zip = new JSZip();

// 向Zip中添加文件
zip.file("hello.txt", "Hello World\n");
zip.file("foo/bar.txt", "Bar\n");

// 将Zip打包成Blob对象
zip.generateAsync({type:"blob"})
.then(function(content) {
    // 下载Zip文件
    saveAs(content, "example.zip");
});

在上面的代码中,我们使用generateAsync()方法将Zip打包成一个Blob对象,并通过saveAs()函数将其保存为一个名为"example.zip"的文件。

generateAsync()方法接受一个参数options,用于指定生成Zip文件的选项。常用的选项如下:

  • type: 指定生成的数据类型,可以是"blob"、"base64"或"uint8array"等。
  • compression: 指定压缩方式,可以是"STORE"、"DEFLATE"或"NONE"等。
  • comment: 添加注释到Zip文件中。

对于大文件或大量文件的打包,可能会耗费一定时间。因此,在生成Zip时,我们需要注意避免阻塞UI线程,以保证用户体验。可以使用generateAsync()方法的progress回调函数来显示进度条或提示信息。

// 创建一个Zip实例
var zip = new JSZip();

// 向Zip中添加文件
zip.file("hello.txt", "Hello World\n");
zip.file("foo/bar.txt", "Bar\n");

// 将Zip打包成Blob对象
zip.generateAsync({
    type: "blob",
    compression: "DEFLATE",
    comment: "This is a test Zip file."
}, function updateCallback(metadata) {
    // 显示压缩进度
    var percent = metadata.percent.toFixed(2);
    console.log(percent + "% done");
})
.then(function(content) {
    // 下载Zip文件
    saveAs(content, "example.zip");
});

在上面的代码中,我们指定了压缩方式为DEFLATE,并添加了一个注释。然后,我们在generateAsync()方法的第二个参数中传入一个回调函数updateCallback,用于更新压缩进度。该回调函数会在压缩过程中多次被调用,每次调用时都会传入一个metadata对象,其中包含了当前压缩进度、已压缩字节数等信息。

打包成Base64字符串

要将Zip打包成Base64字符串,我们可以使用generateAsync()方法的base64参数。

// 创建一个Zip实例
var zip = new JSZip();

// 向Zip中添加文件
zip.file("hello.txt", "Hello World\n");
zip.file("foo/bar.txt", "Bar\n");

// 将Zip打包成Base64字符串
zip.generateAsync({type:"base64"})
.then(function(base64) {
    // 下载Zip文件
    var link = document.createElement("a");
    link.href = "data:application/zip;base64," + base64;
    link.download = "example.zip";
    link.click();
});

在上面的代码中,我们使用generateAsync()方法将Zip打包成一个Base64字符串,并通过设置a标签的href属性来下载Zip文件。

打包成Uint8Array

要将Zip打包成Uint8Array类型的数据,我们可以使用generateAsync()方法的uint8array参数。

// 创建一个Zip实例
var zip = new JSZip();

// 向Zip中添加文件
zip.file("hello.txt", "Hello World\n");
zip.file("foo/bar.txt", "Bar\n");

// 将Zip打包成Uint8Array
zip.generateAsync({type:"uint8array"})
.then(function(data) {
    // 下载Zip文件
    var blob = new Blob([data], {type: "application/zip"});
    saveAs(blob, "example.zip");
});

在上面的代码中,我们使用generateAsync()方法将Zip打包成一个Uint8Array,并通过Blob对象将其保存为一个Zip文件。

读取Zip文件

使用JSZip,我们不仅可以创建和修改Zip文件,还可以读取已有的Zip文件并获取其中的内容。下面是一个简单的例子,演示了如何读取Zip文件中的文件内容:

// 从URL加载Zip文件
JSZipUtils.getBinaryContent("example.zip", function(err, data) {
    if (err) throw err;

    // 解析Zip文件
    JSZip.loadAsync(data)
    .then(function(zip) {
        // 读取Zip中的文件
        var txt = zip.file("hello.txt").async("string");
        return txt;
    })
    .then(function(txt) {
        // 显示文件内容
        console.log(txt);
    });
});

在上面的代码中,我们首先使用JSZipUtils库中的getBinaryContent()方法从URL加载一个Zip文件,并将其解析为一个Zip实例。然后,我们使用file()方法获取Zip中的文件对象,并使用async()方法将文件内容异步读取为字符串类型。

除了使用async()方法异步读取文件内容外,我们还可以使用nodeStream()、arrayBuffer()、blob()等方法来读取文件内容。例如:

// 读取Zip中的文件(使用nodeStream方式)
var stream = zip.file("hello.txt").nodeStream();
stream.on("data", function(data) {
    console.log(data.toString());
});

在上面的代码中,我们使用nodeStream()方法将文件内容读取为一个Node.js流,并通过监听"data"事件来读取文件内容。

修改Zip文件

使用JSZip,我们可以非常方便地修改已有的Zip文件。下面是一个简单的例子,演示了如何向Zip文件中添加文件:

// 从URL加载Zip文件
JSZipUtils.getBinaryContent("example.zip", function(err, data) {
    if (err) throw err;

    // 解析Zip文件
    JSZip.loadAsync(data)
    .then(function(zip) {
        // 向Zip中添加一个文件
        zip.file("new.txt", "Hello New File\n");

        // 将Zip打包成Blob对象并下载
        return zip.generateAsync({type:"blob"});
    })
    .then(function(content) {
        saveAs(content, "example_new.zip");
    });
});

在上面的代码中,我们首先使用getBinaryContent()方法从URL加载一个Zip文件,并将其解析为一个Zip实例。然后,我们使用file()方法向Zip中添加一个新文件,最后将Zip打包成Blob对象并下载。

除了添加文件外,我们还可以使用remove()、rename()等方法删除或重命名Zip文件中的文件。例如:

// 从URL加载Zip文件
JSZipUtils.getBinaryContent("example.zip", function(err, data) {
    if (err) throw err;

    // 解析Zip文件
    JSZip.loadAsync(data)
    .then(function(zip) {
        // 删除Zip中的一个文件
        zip.remove("foo/bar.txt");

        // 重命名Zip中的一个文件
        zip.file("hello_new.txt", zip.file("hello.txt").async("arraybuffer"));

        // 将Zip打包成Blob对象并下载
        return zip.generateAsync({type:"blob"});
    })
    .then(function(content) {
        saveAs(content, "example_new.zip");
    });
});

在上面的代码中,我们使用remove()方法删除Zip中的一个文件,并使用file()方法重命名另一个文件。

总结

JSZip是一个非常强大的JavaScript库,能够方便地创建、读取和修改Zip文件。它支持多种压缩算法和数据类型,并提供了丰富的API和选项,使得开发者可以轻松地实现各种Zip操作。如果你需要处理Zip文件,不妨尝试一下JSZip吧!