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();
});
完整的程式碼如下:
<!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)