JavaScriptを使用してファイルを圧縮パッケージ(.zip)にする方法

2025年3月9日

現代のWeb開発では、ファイルの圧縮は一般的な要件です。ユーザーは複数のファイルを圧縮パッケージにまとめてダウンロードしたり、Webアプリケーションを通じてファイルを生成し、.zipファイルとしてエクスポートしたりする必要があるかもしれません。このブログ記事では、ブラウザでJavaScriptを使用してファイルのパッケージ化と圧縮操作を実装する方法について詳しく説明します。人気のJavaScriptライブラリであるJSZipを使用してこの作業を行い、FileSaver.jsを活用してファイルのダウンロードを実現します。

準備

まず、よく使われる2つのライブラリをインストールする必要があります:

  1. JSZip:これは.zipファイルの作成と処理に使用される軽量のJavaScriptライブラリです。
  2. FileSaver.js:このライブラリは、ブラウザのファイルダウンロードをトリガーするためのクロスブラウザの方法を提供します。

これらのライブラリをプロジェクトにインストールするには:

npm install jszip file-saver

またはCDNを介して含める(HTMLで使用する場合):

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js"></script>

ユーティリティ関数の実装

次に、複数のファイルを.zipファイルにパッケージ化してダウンロードをトリガーするカプセル化されたユーティリティ関数を作成します。一連の画像をパッケージ化したいとしましょう。これらは元のファイルでも、処理後のファイルでもかまいません。

汎用的なdownloadFilesAsZip関数

import JSZip from "jszip";
import { saveAs } from "file-saver";

/**
 * 複数のファイルをZipファイルとしてパッケージ化してダウンロードする
 * @param {Array} files - ファイルオブジェクトの配列、各オブジェクトにはURLとファイル名が含まれる
 * @param {string} zipName - 生成されるZipファイルの名前、デフォルトは'download.zip'
 */
export const downloadFilesAsZip = async (files, zipName = "download.zip") => {
  // 新しいJSZipインスタンスを作成
  const zip = new JSZip();

  // mapを使用して各ファイルを処理するPromiseの配列を作成
  const fetchPromises = files.map(async (file) => {
    try {
      // ファイルリソースをリクエスト、ファイルはURLを介して提供されると仮定
      const response = await fetch(file.url); // ファイルリソースを取得
      const blob = await response.blob(); // レスポンスをBlobオブジェクトに変換

      // 提供されたファイル名を使用して、ファイルをzipパッケージに追加
      zip.file(file.name, blob);
    } catch (error) {
      console.error(`ファイルの追加に失敗しました: ${file.name}`, error);
    }
  });

  // すべてのファイルがダウンロードされ、Zipに追加されるのを待つ
  await Promise.all(fetchPromises);

  // zipパッケージのコンテンツを生成(blobタイプ)
  const content = await zip.generateAsync({ type: "blob" });

  // FileSaver.jsを使用してzipパッケージをダウンロード
  saveAs(content, zipName);
};

コードの説明

  • JSZipインスタンスの作成:const zip = new JSZip(); — 新しいZipファイルインスタンスを作成し、すべてのファイルがこのインスタンスに追加されます。
  • ファイルのダウンロードとパッケージ化:fetch()関数を使用してURLからファイルのコンテンツを取得し、それをblob形式に変換します。これは、JSZipblob形式でファイルを処理できるためです。
  • .zipファイルの生成:zip.generateAsync({ type: "blob" })を通じて、zipオブジェクトに追加されたすべてのファイルを.zipファイルに圧縮し、blobオブジェクトを返します。
  • ファイルの保存:FileSaver.jsを使用してsaveAs(content, zipName)でファイルダウンロードをトリガーします。ここでcontentは生成されたzipパッケージ、zipNameはダウンロードファイル名です。

このユーティリティ関数の使用方法

画像URLのセットがあり、それらを.zipファイルにパッケージ化してダウンロードしたいとします。以下はdownloadFilesAsZip関数を呼び出す例です:

// サンプルファイルデータ:ファイルURLとファイル名を含む
const files = [
  { url: "https://example.com/image1.jpg", name: "image1.jpg" },
  { url: "https://example.com/image2.jpg", name: "image2.jpg" },
  { url: "https://example.com/image3.jpg", name: "image3.jpg" },
];

// 関数を呼び出してファイルをダウンロードし、zipファイルとしてパッケージ化
downloadFilesAsZip(files, "images.zip");

この例では、画像URLとファイル名を含むオブジェクトの配列を提供しています。downloadFilesAsZip関数を呼び出した後、ブラウザは自動的にダウンロード操作をトリガーし、これらの画像をimages.zipという名前の圧縮ファイルにパッケージ化します。

一般的な問題と解決策

  1. クロスオリジンの問題 ファイルが異なるドメインから来る場合、サーバーが正しいクロスオリジンリソース共有(CORS)ヘッダーを設定していることを確認してください。そうでなければ、ブラウザはfetch()リクエストをブロックし、ファイルのダウンロードができなくなります。
  2. 大きなファイルのダウンロード ダウンロードするファイルが大きい場合、チャンクダウンロードやプログレスバーの表示など、ダウンロードプロセスを最適化する必要があるかもしれません。
  3. ブラウザのサポート この方法はfetch()とFileSaver.jsに依存しているため、これらのAPIをサポートする最新のブラウザが必要です。古いブラウザをサポートする必要がある場合は、ポリフィルの使用を検討してください。

代替ソリューション

JSZipとFileSaver.jsを使用する以外にも、ブラウザでファイル圧縮とパッケージ化を実装するためのいくつかの一般的なソリューションがあります:

  1. Pako.jsPakoはJavaScript用のzlib圧縮ライブラリで、gzipとdeflate形式をサポートしています。小さなファイルの圧縮に適しており、比較的使いやすいです。
  2. Archiver.jsArchiver.jsは機能豊富なライブラリで、.tar.zipなどの形式への圧縮をサポートしています。ブラウザでファイル圧縮を実行でき、より多くの制御オプションを提供します。
  3. zip.jszip.jsはストリーミング解凍と圧縮をサポートするJavaScriptライブラリで、より大きなファイルを処理でき、.zipファイルへの圧縮機能を提供します。
  4. BrowserFS + zip-libBrowserFSはブラウザでファイルシステムシミュレーションを提供するライブラリです。zip-libと組み合わせることで、.zipファイルを作成してダウンロードでき、ファイルシステムをシミュレートする必要があるアプリケーションに適しています。