芽萌丸プログラミング部 @programming
@programming
2021/12/22 9:50 更新✏

ブラウザ上でzip圧縮

ブラウザ上だけでファイルやデータをzip圧縮する方法のメモです。

目次:

サンプルコード

以下のサンプルでは、ブラウザ画面上のファイルINPUTでファイルを入力すると、それをzip圧縮したzipファイルをダウンロード風に出力します。処理は全てブラウザローカルだけで完結しています。 zip圧縮ライブラリにはJSZipモジュールを利用しています。 (動作確認はChromeブラウザのみ)

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title></title>
</head>

<body>
  <input type="file" oninput="onFileInput(event)">
  <script src="https://cdn.jsdelivr.net/npm/jszip@3.7.1/dist/jszip.min.js" integrity="sha256-yeSlK6wYruTz+Q0F+8pgP1sPW/HOjEXmC7TtOiyy7YY=" crossorigin="anonymous"></script>
  <script type="text/javascript">
  /**
   * ファイル入力ハンドラ
   * @param  {Event} e
   */
  function onFileInput(e) {
    const filename = "example.zip";
    const file = e.target.files && e.target.files.length >= 1 ? e.target.files[0] : null;
    if (!file) return;
    const reader = new FileReader();
    reader.onload = function(e) {
      // ファイル内容:
      const content = new Uint8Array(e.target.result); // as blob
      // const content = e.target.result; // as text
      return zipcompress([
        ["foo/" + file.name, content], // zip内のfoo/配下に読み込んだ内容を設置
        // 圧縮対象ファイルの複数指定も可能:
        // ["aaa.txt", "helloworld!"],
        // ["bbb/bbb.txt", "helloworld!"],
      ], (err, result) => {
        return download(result, filename);
      });
    };
    reader.readAsArrayBuffer(file); // read as arraybuffer
    // reader.readAsText(file); // read as text
  }
  /**
   * [汎用] ブラウザでのダウンロード処理
   * @param  {String|Uint8Array} content
   * @param  {String} filename - filename of output data.
   */
  function download(content, filename) {
    // create a temporary "a" element.
    const a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display:none";
    const blob = new Blob([content], { type: "octet/stream" });
    // or
    // const blob = new Blob([new Uint8Array([72, 101, 108, 108, 111])], {...});
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url); // release the used object.
    a.parentNode.removeChild(a); // delete the temporary "a" element
  }

  /**
   * zip圧縮したデータを返します。
   * @param  {Array<[path,data]>}   pathAndDataList
   * @param  {Function} cb
   * @return {Blob}
   */
  function zipcompress(pathAndDataList, cb) {
    if (typeof JSZip === "undefined")
      throw Error("JSZip must be installed.");
    const zip = new JSZip();
    for (let len = pathAndDataList.length, i = 0; i < len; i++) {
      const [filename, data] = pathAndDataList[i];
      zip.file(filename, data);
    }
    return zip.generateAsync({
      type: "blob",
      compression: "DEFLATE",
      compressionOptions: {
        /* compression level ranges from 1 (best speed) to 9 (best compression) */
        level: 9
      },
    }).then(function(content) {
      return cb && cb(null, content); // content is blob type.
    });
  }
  </script>
</body>

</html>

実行

以上です。

zip

芽萌丸プログラミング部 @programming
芽萌丸プログラミング部@programming
プログラミング関連アカウント。Web標準技術を中心に書いていきます。フロントエンドからサーバサイドまで JavaScript だけで済ませたい人たちの集いです。記事は主に @TanakaSoftwareLab が担当。
オススメ:Zattoyomiで時事ネタチェックの時間節約!