Node.jsを使用してディレクトリ全体をZIPする必要があります


107

Node.jsを使用してディレクトリ全体を圧縮する必要があります。私は現在node-zipを使用しており、プロセスが実行されるたびに無効なZIPファイルが生成されます(このGithubの問題からわかるように)。

ディレクトリをZIP圧縮できる別の優れたNode.jsオプションはありますか?

編集:私はアーカイバーを使用してしまいました

writeZip = function(dir,name) {
var zip = new JSZip(),
    code = zip.folder(dir),
    output = zip.generate(),
    filename = ['jsd-',name,'.zip'].join('');

fs.writeFileSync(baseDir + filename, output);
console.log('creating ' + filename);
};

パラメータのサンプル値:

dir = /tmp/jsd-<randomstring>/
name = <randomstring>

更新:私が使用した実装について質問する人のために、ここに私のダウンローダーへのリンクがあります


3
Twitterで誰かがchild_process APIを提案し、単にシステムのZIP呼び出す:nodejs.org/api/child_process.html
commadelimited

1
child_processアプローチを試しました。2つの注意点があります。 1) unix zipコマンドは、現在の作業ディレクトリのすべての親フォルダ階層を圧縮ファイルに含めます。これはあなたにとっては大丈夫かもしれませんが、私にとってはそうではありませんでした。また、child_processの現在の作業ディレクトリを変更しても、結果には影響しません。 2)この問題を克服するために、あなたが使用する必要がありpushdますが、ジッパーするフォルダに飛び込むとするzip -rが、以来、pushd bashのではなく/ binに/ shのに組み込まれています。また、使用/ binに/ bashをする必要があります。私の特定のケースでは、これは不可能でした。頭を上げただけです。
johnozbay 16

2
@johnozbayノードのchild_process.execapiでは、コマンドを実行する場所からcwdを指定できます。CWDを変更すると、親フォルダー階層の問題が修正されます。また、不要な問題も修正されpushdます。child_processをお勧めします。
Govind Rai

1
stackoverflow.com/a/49970368/2757916 child_process apiを使用したネイティブのnodejsソリューション。2行のコード。サードパーティのライブラリはありません。
Govind Rai

@GovindRaiありがとうございます!
johnozbay 2018

回答:


123

最終的にアーカイバ lib を使用しました。よく働く。

var file_system = require('fs');
var archiver = require('archiver');

var output = file_system.createWriteStream('target.zip');
var archive = archiver('zip');

output.on('close', function () {
    console.log(archive.pointer() + ' total bytes');
    console.log('archiver has been finalized and the output file descriptor has closed.');
});

archive.on('error', function(err){
    throw err;
});

archive.pipe(output);

// append files from a sub-directory and naming it `new-subdir` within the archive (see docs for more options):
archive.directory(source_dir, false);
archive.finalize();

1
これを行う方法の例はないようですが、あなたがしたことを共有していただけませんか?
Sinetheta 2013

1
残念ながら、現在、アーカイバはファイル名のUnicode文字をサポートしていません。github.com/ctalkington/node-archiver/issues/90に報告されました
2014

2
すべてのファイルとディレクトリを再帰的に含めるにはどうすればよいですか(隠しファイル/ディレクトリも)。
IonicăBizău

12
Archiverはこれをさらに簡単にします。bulk()メソッドを使用する代わりに、directory()を使用できるようになりました:npmjs.com/package/archiver#directory-dirpath-destpath-data
Josh Feldman

14
.bulkは非推奨です
チョビー

46

私は何か新しいものを示すふりはしません。コードの中でPromise関数を使用したい人(私のように)のために上記の解決策を要約したいだけです。

const archiver = require('archiver');

/**
 * @param {String} source
 * @param {String} out
 * @returns {Promise}
 */
function zipDirectory(source, out) {
  const archive = archiver('zip', { zlib: { level: 9 }});
  const stream = fs.createWriteStream(out);

  return new Promise((resolve, reject) => {
    archive
      .directory(source, false)
      .on('error', err => reject(err))
      .pipe(stream)
    ;

    stream.on('close', () => resolve());
    archive.finalize();
  });
}

それが誰かを助けることを願っています;)


ここで正確に「アウト」とは何ですか?ソースがディレクトリのパスであると仮定します
Dreams

@Tarunの完全なzipのパス:/User/mypc/mydir/test.zip
D.Dimitrioglo

zipファイルを解凍できません。操作は許可されていません
Jake

@ ekaj_03指定したディレクトリに対して十分な権限があることを確認してください
D.Dimitrioglo

1
@ D.Dimitriogloすべて良い。これは、ソースディレクトリの問題でした。ありがとう:)
Jake

17

これを行うには、Nodeのネイティブchild_processAPIを使用します。

サードパーティのライブラリは必要ありません。2行のコード。

const child_process = require("child_process");
child_process.execSync(`zip -r DESIRED_NAME_OF_ZIP_FILE_HERE *`, {
  cwd: PATH_TO_FOLDER_YOU_WANT_ZIPPED_HERE
});

同期APIを使用しています。child_process.exec(path, options, callback)非同期が必要な場合に使用できます。CWDを指定するだけでなく、リクエストをさらに微調整するためのオプションがたくさんあります。exec / execSyncドキュメントを参照してください。


注意: この例では、システムにzipユーティリティがインストールされていることを前提としています(少なくともOSXに付属しています)。一部のオペレーティングシステムにはユーティリティがインストールされていない場合があります(つまり、AWS Lambdaランタイムにはインストールされていません)。その場合、ここで簡単にzipユーティリティバイナリを取得し、アプリケーションソースコードと一緒にパッケージ化できます(AWS Lambdaの場合はLambdaレイヤーにもパッケージ化できます)。または、サードパーティのモジュールを使用する必要があります。 (そのうちNPMにはたくさんあります)。ZIPユーティリティは何十年も試され、テストされているため、私は前者のアプローチを好みます。


9
残念ながら、が搭載されているシステムでのみ機能しますzip
janpio

3
私のプロジェクトで数十の外部ライブラリを回避するためだけにこのソリューションに参加しました
EAzevedo

それは理にかなっていますが、私が正しくない場合、これは再びWindowsユーザーをねじ込みます。Windowsユーザーのことを考えてください!
Mathijs Segers、

@mathijsSegersははは!そのため、Windowsユーザーもバイナリを取得できるように、バイナリへのリンクを含めました。:)
Govind Rai

これをコンピュータディレクトリではなくプロジェクト内のディレクトリで機能させる方法はありますか?
Matt

13

Archive.bulkは非推奨になりました。これに使用する新しいメソッドはglobです。

var fileName =   'zipOutput.zip'
var fileOutput = fs.createWriteStream(fileName);

fileOutput.on('close', function () {
    console.log(archive.pointer() + ' total bytes');
    console.log('archiver has been finalized and the output file descriptor has closed.');
});

archive.pipe(fileOutput);
archive.glob("../dist/**/*"); //some glob pattern here
archive.glob("../dist/.htaccess"); //another glob pattern
// add as many as you like
archive.on('error', function(err){
    throw err;
});
archive.finalize();

2
これについて疑問に思っていた彼らは、バルクは廃止予定であると述べましたが、代わりに使用する関数を提案していませんでした。
jarodsmk 2017年

1
「ソース」ディレクトリをどのように指定しますか?
Dreams

:アプローチ下記一度試してみてくださいjsonworld.wordpress.com/2019/09/07/...
曽爾クマリ

2020:archive.directory()ははるかに単純です!
OhadR


9

これは、フォルダーを1行で圧縮する別のライブラリーです: zip-local

var zipper = require('zip-local');

zipper.sync.zip("./hello/world/").compress().save("pack.zip");

4
いつも私のための「ゼロバイト」ファイルを生成した魅力、インターネット上で利用可能か、上記の他のとは異なりダース、のように働いた
セルゲイPleshakov

4

結果を応答オブジェクトにパイプする(ローカルに保存するのではなく、zipをダウンロードする必要があるシナリオ)

 archive.pipe(res);

ディレクトリのコンテンツにアクセスするためのサムのヒントは私にとってはうまくいきました。

src: ["**/*"]

3

Adm-zipには、既存のアーカイブhttps://github.com/cthackers/adm-zip/issues/64を圧縮するだけでなく、バイナリファイルを圧縮すると破損する問題があります。

node-zip https://github.com/daraosn/node-zip/issues/4で圧縮破損の問題も発生しました

node-archiverは、圧縮にうまく機能しているように見える唯一のものですが、圧縮解除機能はありません。


1
どのノードアーカイバーについて話しているのですか?:github.com/archiverjs/node-archiver; github.com/richardbolt/node-archiver
biphobe

@firianアーカイバーは言わなかった、とAdm-zipは言った。
Francis Pelland 2016年

5
@FrancisPellandうーん、最後の文で彼が書いた「ノードアーカイバーだけが動作するように見える」-それは私が言及しているものです。
ビフォーブ2016年

私は彼がnpmjs.com/package/archiverを食う
OhadR

2

私はあなたが必要とするものをカプセル化するこの小さなライブラリを見つけました。

npm install zip-a-folder

const zip-a-folder = require('zip-a-folder');
await zip-a-folder.zip('/path/to/the/folder', '/path/to/archive.zip');

https://www.npmjs.com/package/zip-a-folder


パラメータを追加してzipフォルダを作成することは可能ですか?圧縮されたレベルとサイズが好きならどうすればいいですか?
Trang D

1

以来archiver、長い時間のためのWebPACKの新バージョンと互換性がありません、私が使用することをお勧めZIP-libが

var zl = require("zip-lib");

zl.archiveFolder("path/to/folder", "path/to/target.zip").then(function () {
    console.log("done");
}, function (err) {
    console.log(err);
});

0

あなたは簡単な方法で試すことができます:

インストールzip-dir

npm install zip-dir

そしてそれを使う

var zipdir = require('zip-dir');

let foldername =  src_path.split('/').pop() 
    zipdir(<<src_path>>, { saveTo: 'demo.zip' }, function (err, buffer) {

    });

パラメータを追加してzipフォルダを作成することは可能ですか?圧縮されたレベルとサイズが好きならどうすればいいですか?
Trang D

0

私のプロジェクト全体のリファクタリングには多大な労力がかかるため、JSBipをエミュレートするためにアーカイバをラップすることになりました。Archiverが最良の選択ではない可能性があることを理解していますが、ここで始めます。

// USAGE:
const zip=JSZipStream.to(myFileLocation)
    .onDone(()=>{})
    .onError(()=>{});

zip.file('something.txt','My content');
zip.folder('myfolder').file('something-inFolder.txt','My content');
zip.finalize();

// NodeJS file content:
    var fs = require('fs');
    var path = require('path');
    var archiver = require('archiver');

  function zipper(archive, settings) {
    return {
        output: null,
        streamToFile(dir) {
            const output = fs.createWriteStream(dir);
            this.output = output;
            archive.pipe(output);

            return this;
        },
        file(location, content) {
            if (settings.location) {
                location = path.join(settings.location, location);
            }
            archive.append(content, { name: location });
            return this;
        },
        folder(location) {
            if (settings.location) {
                location = path.join(settings.location, location);
            }
            return zipper(archive, { location: location });
        },
        finalize() {
            archive.finalize();
            return this;
        },
        onDone(method) {
            this.output.on('close', method);
            return this;
        },
        onError(method) {
            this.output.on('error', method);
            return this;
        }
    };
}

exports.JSzipStream = {
    to(destination) {
        console.log('stream to',destination)
        const archive = archiver('zip', {
            zlib: { level: 9 } // Sets the compression level.
        });
        return zipper(archive, {}).streamToFile(destination);
    }
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.