Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

nodejsでパスワード付き圧縮ファイルを生成し、サーバーから送信してみる

前回、http requestを受けてからzip圧縮ファイルを生成しフロントエンドに圧縮したzipファイルを送信するまでを実施しました。
elsammit-beginnerblg.hatenablog.com

今回はzip圧縮だけではなくパスワードを付けて送信してみたいと思います。



■環境

前回と同様の構成で行きます。
f:id:Elsammit:20211108231936p:plain

言語はnodejs(サーバーサイドjavascritpt)です。

■パスワード付き圧縮ファイル生成コード その1

では早速パスワード付き圧縮ファイルを生成するコードを書いていきます。

まずはライブラリを用いてパスワード付きzipファイルを生成する方法からです。
今回用いるライブラリは、
「archiver-zip-encryptable」
です。
github.com

まず下記でライブラリをダウンロードしてきます。

npm i archiver-zip-encryptable

そして、archiver-zip-encryptableを用いたzipパスワード付き圧縮ファイルを生成するコードはこちらになります。

const fs = require('fs')
const archiver = require('archiver');

archiver.registerFormat('zip-encryptable', require('archiver-zip-encryptable'));

function zipCompression(){
    let zip_file_name = "src.zip";

    // ストリームを生成して、archiverと紐付ける
    var archive = archiver('zip-encryptable', {
        zlib: { level: 9 },
        encryptionMethod: 'aes256',
        password: 'test'
    });
    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');
    
    // zip圧縮実行
    archive.finalize();
}

まず、

archiver.registerFormat('zip-encryptable', require('archiver-zip-encryptable'));

にてarchiverにパスワード付きzipを生成するように設定(定義)を行います。

後は'archiver生成時に、

    var archive = archiver('zip-encryptable', {
        zlib: { level: 9 },
        encryptionMethod: 'aes256',
        password: 'test'
    });

のように暗号化方式やパスワードをセットすればOK。
後は、zip圧縮と同様に、
にて圧縮ファイルに各データを入れていきます。
圧縮するデータはimgディレクトリ配下全てとしています。

こちらを実行するとsrc.zipが生成されており、解凍しようとするとパスワードを求められるかと思います。
さらに、パスワードに"test"と入力すると解凍が実行され、imgディレクトリ配下が格納されていることが確認できるかと思います。

■パスワード付き圧縮ファイル生成コード その2

先ほどはライブラリを用いてパスワード付きzip圧縮化を実施しました。

今度はサーバー側OSがLinux系に限定されてしまいますが、
新規にライブラリをダウンロードせずに実現する方法についてまとめていきます。

方法は、Linuxのコマンドをnodejs上で実行してしまう方法です。
コードはこちら。

const child = require('child_process');

function zipCompression(){
    var zip_file_name = "src.zip";

    spawn = child.spawn;
    zip = spawn('zip',['-P', 'password' , zip_file_name, "-r" , "img"]);
}

child_processを用いて、

spawn = child.spawn;
zip = spawn('zip',['-P', 'test' , zip_file_name, "-r" , "img"]);

で圧縮コマンドを実行していきます。

child_processについての詳細は下記を参考にしてください。
Child process | Node.js v17.1.0 Documentation

今回実施していることは、
zipコマンドで、-Pオプションを用いてパスワードを付与してzip圧縮するコードを生成させ、
実行しているのみです。

こちらも実行すると圧縮されたファイルが生成され、解凍する際にパスワード(test)の入力が求められるかと思います。

■requestに応じてパスワード付き圧縮ファイル生成しresponseするコード

最後は前回と同様に、パスワード付き圧縮ファイルを生成しresponseしてみたいと思います。
掲載するのはzip-encryptableライブラリを用いる方法です。

const fs = require('fs')
var http = require('http');
const archiver = require('archiver');

archiver.registerFormat('zip-encryptable', require('archiver-zip-encryptable'));

function zipFiles() {
    return new Promise(function (resolve){
        // 出力先のzipファイル名
        var zip_file_name = "src.zip";

        // ストリームを生成して、archiverと紐付ける
        var archive = archiver('zip-encryptable', {
            zlib: { level: 9 },
            encryptionMethod: 'aes256',
            password: 'test'
        });
        var output = fs.createWriteStream(zip_file_name);
        archive.pipe(output);

        archive.glob('img/*');
        
        // zip圧縮実行
        archive.finalize();
        output.on("close", function () {
            // zip圧縮完了すると発火する
            var archive_size = archive.pointer();
            console.log(`complete! total size : ${archive_size} bytes`);

            resolve(0);
        });
    });
}

function zipCompression(){
    var zip_file_name = "src.zip";

    // ストリームを生成して、archiverと紐付ける
    var archive = archiver('zip-encryptable', {
        zlib: { level: 9 },
        encryptionMethod: 'aes256',
        password: 'test'
    });
    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');
    
    // zip圧縮実行
    archive.finalize();
}

http.createServer(function(req,res){
    zipFiles().then(function(data){
        var fileName = "src.zip";
        var contentDip = 'attachment; filename=' + fileName;
        
        res.writeHead(200, {
            'Content-Type': 'application/zip',
            'Content-Disposition' : contentDip
        });
        var readStream = fs.createReadStream('src.zip');

        readStream.pipe(res);
    });
}).listen(8080);

こちらのコードを実行後、

curl -o test.zip http://ipアドレス:8080/

というようにcurlコマンドでファイルをダウンロードすると、サーバーからデータがzip圧縮された状態で格納され、
解凍する際にはパスワードの入力が求められるかと思います。

■最後に

今回はパスワード付きzipファイルを生成する方法と、
http requestに応じて生成したパスワード付きzipファイルをresponseするまでをまとめてみました。