147

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>

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

4

13 に答える 13

175

アーカイバライブラリを使用することになりました。よく働く。

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

var output = fs.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, putting its contents at the root of archive
archive.directory(source_dir, false);

// append files from a sub-directory and naming it `new-subdir` within the archive
archive.directory('subdir/', 'new-subdir');

archive.finalize();
于 2013-09-12T22:06:43.827 に答える
99

私は何か新しいことを示すつもりはありません。私と同じくらいPromisesが好きな人のために、上記の解決策を要約したかっただけです。

const archiver = require('archiver');

/**
 * @param {String} sourceDir: /some/folder/to/compress
 * @param {String} outPath: /path/to/created.zip
 * @returns {Promise}
 */
function zipDirectory(sourceDir, outPath) {
  const archive = archiver('zip', { zlib: { level: 9 }});
  const stream = fs.createWriteStream(outPath);

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

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

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

于 2018-07-25T11:46:18.450 に答える
32

これを実現するには、 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ユーティリティは何十年にもわたって試され、テストされているので、私は前者のアプローチを好みます。

于 2018-04-22T20:20:30.643 に答える
14

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

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

zipper.sync.zip("./hello/world/").compress().save("pack.zip");
于 2018-07-30T11:27:41.850 に答える
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();
于 2016-11-22T07:40:17.607 に答える
9

すべてのファイルとディレクトリを含めるには:

archive.bulk([
  {
    expand: true,
    cwd: "temp/freewheel-bvi-120",
    src: ["**/*"],
    dot: true
  }
]);

下にあるnode-glob(https://github.com/isaacs/node-glob)を使用するため、これと互換性のある一致する式はすべて機能します。

于 2015-01-14T03:19:26.553 に答える
4

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

 archive.pipe(res);

ディレクトリのコンテンツにアクセスするためのSamのヒントは私のために働いた。

src: ["**/*"]
于 2015-08-28T13:38:46.773 に答える
3

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

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

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

于 2013-09-11T21:41:24.857 に答える
3

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

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

于 2018-10-01T21:04:51.687 に答える
2

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);
});
于 2019-10-12T10:21:29.073 に答える
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) {

    });
于 2018-11-12T10:46:16.653 に答える
0

プロジェクト全体のリファクタリングには多大な労力がかかるため、アーカイバをラップしてJSZipをエミュレートすることになりました。アーカイバが最善の選択ではないかもしれないことは理解していますが、ここに行きます。

// 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);
    }
};
于 2020-03-11T15:15:50.133 に答える
0

import ... fromhttps://stackoverflow.com/a/51518100に基づく回答

単一のディレクトリを圧縮するには

import archiver from 'archiver';
import fs from 'fs';

export default zipDirectory;

/**
 * From: https://stackoverflow.com/a/51518100
 * @param {String} sourceDir: /some/folder/to/compress
 * @param {String} outPath: /path/to/created.zip
 * @returns {Promise}
 */
function zipDirectory(sourceDir, outPath) {
  const archive = archiver('zip', { zlib: { level: 9 }});
  const stream = fs.createWriteStream(outPath);

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

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

複数のディレクトリを圧縮するには:

import archiver from 'archiver';
import fs from 'fs';

export default zipDirectories;

/**
 * Adapted from: https://stackoverflow.com/a/51518100
 * @param {String} sourceDir: /some/folder/to/compress
 * @param {String} outPath: /path/to/created.zip
 * @returns {Promise}
 */
function zipDirectories(sourceDirs, outPath) {
  const archive = archiver('zip', { zlib: { level: 9 }});
  const stream = fs.createWriteStream(outPath);

  return new Promise((resolve, reject) => {
    var result = archive;
    sourceDirs.forEach(sourceDir => {
      result = result.directory(sourceDir, false);
    });
    result
      .on('error', err => reject(err))
      .pipe(stream)
    ;

    stream.on('close', () => resolve());
    archive.finalize();
  });
}
于 2022-02-02T16:09:42.153 に答える