# [Node.js]ファイルをZIP圧縮してダウンロードする方法 ## 圧縮処理について * 方法1:フロンサイドで圧縮データを処理しファイルを保存する(JSZip) * 方法2:サーバサイドで圧縮処理しファイルを出力する * 方法3:サーバサイドで圧縮処理しフロントでBlobによりファイルを取得する ### 方法1:フロンサイドで圧縮データを処理しファイルを保存する(JSZip) * **ファイル量が多い場合(30MB以上など)はサーバーサイドで処理するほうがいい** * 大容量データの処理には向かない * ユーザーのデバイスの性能に依存する ```mermaid sequenceDiagram User->>Front: ダウンロードボタンを要求する loop ファイル毎に処理する Front->>Storage: ファイルを要求する(fetch) Storage-->>Front: ファイル情報を返す end Front-->>Front: Zip処理を実行する(JSZip) Front-->>User: ダウンロード処理を実行する(blob) ``` * https://stuk.github.io/jszip/documentation/examples.html * [サンプルコード](../src/front/assets/download.js) ``` import JSZip from "jszip"; ``` **CDNでインポートする場合** ```js ``` --- ### 方法2:サーバサイドで圧縮処理しファイルを出力する サーバーサイドでarchiverを使ってZIPを作成し、 一時ファイルとして保存してからダウンロード用のURLを返します * archiverモジュールで実行する * Zipファイルの保存のためにストレージが別で必要 * ライフサイクルを考慮しないと不要なファイルが溜まる * 大容量データの圧縮に適してい * 複数のリクエストに対応しやすい ```mermaid sequenceDiagram User->>Front: ダウンロードボタンを要求する Front->>Server: ダウンロードを要求する Server->>Storage: ファイルデータ取得API Storage->>Server: レスポンス Server->>Server: Zip処理を実行する(archiver) Server->>Storage: 作成した Zipを保存する Storage->>Server: レスポンス Server-->>Front: ファイルのURLを返す Front->>Storage: URLをリンクする(HTTP) Storage-->>User: ファイルをダウンロードする ``` ```sh npm install archiver ``` --- ### 方法3:サーバサイドで圧縮処理しフロントでBlobによりファイルを取得する ZIPを一時ファイルとして保存せずに 直接フロントエンドにストリームとして送信します。 * archiverモジュールで実行する * 保存せずにファイルコンテンツを返す * リアルタイムでファイルをストリーミング可能 * ストレージの管理が不要 * クライアントがダウンロードを途中でキャンセルするとデータが失われる可能性がある ```mermaid sequenceDiagram User->>Front: ダウンロードボタンを要求する Front->>Server: ダウンロードを要求する Server->>Storage: ファイルデータ取得API Storage->>Server: レスポンス Server->>Server: Zip処理を実行する(archiver) Storage->>Front: Zipされたファイルコンテンツを返す Front-->>User: ダウンロード処理を実行する(blob) ``` ## サンプルソース ### Blobを使用してZIPファイルを処理する(フロント側の処理)** ```js fetch("https://example.com/sample.zip") .then(response => response.blob()) .then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "downloaded.zip"; document.body.appendChild(a); a.click(); URL.revokeObjectURL(url); }) .catch(error => console.error("Error downloading ZIP:", error)); ``` #### Gloudにあるファイルをzip形式でファイルを出力するサンプルソース (スクリプト) ```js const { Storage } = require('@google-cloud/storage'); const archiver = require('archiver'); const fs = require('fs'); const storage = new Storage(); const bucketName = 'your-bucket-name'; const filesToDownload = ['file1.csv', 'file2.csv']; // 圧縮したいファイルリスト const outputZip = 'output.zip'; async function downloadAndZip() { const output = fs.createWriteStream(outputZip); const archive = archiver('zip', { zlib: { level: 9 } }); output.on('close', () => { console.log(`Zip file created: ${outputZip} (${archive.pointer()} bytes)`); }); archive.pipe(output); for (const fileName of filesToDownload) { const file = storage.bucket(bucketName).file(fileName); const [exists] = await file.exists(); if (exists) { console.log(`Adding ${fileName} to archive...`); archive.append(file.createReadStream(), { name: fileName }); } else { console.warn(`File not found: ${fileName}`); } } archive.finalize(); } downloadAndZip().catch(console.error); ```