使用JSZip實現在瀏覽器中操作檔案與資料夾

当时明月在曾照彩云归發表於2024-04-19

1. 引言

瀏覽器中如何建立資料夾、寫入檔案呢?

答曰:可以藉助JSZip這個庫來實現在瀏覽器記憶體中建立檔案與資料夾,最後只需下載這個.zip檔案,就是最終得結果

類似的使用場景如下:

  • 線上下載很多圖片,希望這些圖片能分類儲存到各個資料夾並最終下載成一個zip檔案
  • 線上下載很多文件,希望這些文件能分類儲存到各個資料夾並最終下載成一個zip檔案

本質上都是希望瀏覽器能建立資料夾和建立檔案,最終儲存成一個檔案來提供下載

JSZip的GitHub站點:Stuk/jszip: Create, read and edit .zip files with Javascript (github.com)

一個可用的中文站點:JSZip參考手冊 (asprain.cn)

下面主要記錄一下基礎使用,詳細的API請參考上述文件

2. 使用

2.1 安裝

使用NPM:

npm install jszip

使用線上CDN:

<script src="https://cdn.bootcdn.net/ajax/libs/jszip/3.10.1/jszip.js"></script>
  • 為了可以程式碼可以快速復現,筆者這裡使用CDN的方式引入

2.2 建立zip例項

一個JSZip例項是讀寫.zip檔案的基礎

const zip = new JSZip();

2.3 讀取zip檔案

讀取官方的示例檔案text.zip

const zip = new JSZip();

fetch("https://stuk.github.io/jszip/test/ref/text.zip")       // 1) fetch the url
    .then(function (response) {                       // 2) filter on 200 OK
        if (response.status === 200 || response.status === 0) {
            return Promise.resolve(response.blob());
        } else {
            return Promise.reject(new Error(response.statusText));
        }
    })
    .then(data => zip.loadAsync(data))                            // 3) 載入資料
    .then(function (zip) {
        zip.forEach(function (relativePath, file) {  	// 4) 遍歷壓縮包內的檔案
           console.log(`path: ${relativePath}, file: ${file.name}`)
           // 輸出:path: Hello.txt, file: Hello.txt
        });
})

因為Hello.txt是個文字檔案,可以直接使用string的方式讀取內部的資料

const zip = new JSZip();

fetch("https://stuk.github.io/jszip/test/ref/text.zip")       // 1) fetch the url
    .then(function (response) {                       // 2) filter on 200 OK
        if (response.status === 200 || response.status === 0) {
            return Promise.resolve(response.blob());
        } else {
            return Promise.reject(new Error(response.statusText));
        }
    })
    .then(data => zip.loadAsync(data))                            // 3) chain with the zip promise
    .then(function (zip) {
        return zip.file("Hello.txt").async("string"); // 4) 讀取Hello.txt檔案
    })
    .then(function success(text) {
        console.log(text); // 輸出:Hello World
    }, function error(e) {
        console.error(e);
    });

2.4 建立zip檔案

寫入檔案與資料

zip.file("file.txt", "content");
new Promise((resolve, reject) => {
    resolve(zip.file("file.txt").async("string"))
}).then(data => {
    console.log(data); // 輸出:content
})

寫入指定資料夾下的指定檔案

zip.file("text/file.txt", "content");
zip.forEach(function (relativePath, file) {
    console.log(`path: ${relativePath}, file: ${file.name}`)
    // 輸出:path: text/file.txt, file: text/file.txt
});

最後的目錄結構可以參考下圖

2.5 下載zip檔案

這裡將上面的file.txt下載為zip,使用a連結的方式

zip.generateAsync({ type: "blob" }).then(function (content) {
    document.body.appendChild(document.createElement("a"));
    document.querySelector("a").href = URL.createObjectURL(content);
    document.querySelector("a").download = "test.zip";
    document.querySelector("a").click();
});

image

完整的程式碼如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jszip/3.10.1/jszip.js"></script>
</head>

<body>

    <script>
        const zip = new JSZip();

        // fetch("https://stuk.github.io/jszip/test/ref/text.zip")       // 1) fetch the url
        //     .then(function (response) {                       // 2) filter on 200 OK
        //         if (response.status === 200 || response.status === 0) {
        //             return Promise.resolve(response.blob());
        //         } else {
        //             return Promise.reject(new Error(response.statusText));
        //         }
        //     })
        //     .then(data => zip.loadAsync(data))                            // 3) chain with the zip promise
        //     .then(function (zip) {
        //         return zip.file("Hello.txt").async("string"); // 4) chain with the text content
        //     })
        //     .then(function success(text) {
        //         console.log(text);
        //     }, function error(e) {
        //         console.error(e);
        //     });
        zip.file("text/file.txt", "content");
        zip.forEach(function (relativePath, file) { 
           console.log(`path: ${relativePath}, file: ${file.name}`)
        });

        zip.generateAsync({ type: "blob" }).then(function (content) {
            document.body.appendChild(document.createElement("a"));
            document.querySelector("a").href = URL.createObjectURL(content);
            document.querySelector("a").download = "test.zip";
            document.querySelector("a").click();
        });
    </script>

</body>

</html>

3. 參考資料

[1] How to use JSZip (stuk.github.io)

[2] JSZip參考手冊 (asprain.cn)

相關文章