web-dev-qa-db-fra.com

Besoin de compresser un répertoire entier en utilisant Node.js

Je dois compresser un répertoire entier à l'aide de Node.js. J'utilise actuellement node-Zip et chaque fois que le processus s'exécute, il génère un fichier Zip non valide (comme vous pouvez le voir dans ce problème de Github ).

Existe-t-il une autre option, meilleure, Node.js, qui me permettra de compresser un répertoire?

EDIT: J'ai fini par utiliser archiver

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);
};

valeur d'échantillon pour les paramètres:

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

UPDATE: Pour ceux qui me posent des questions sur la mise en œuvre que j'ai utilisée, voici un lien vers mon téléchargeur :

66
commadelimited

J'ai fini par utiliser archiver lib. Fonctionne très bien.

Exemple

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);
archive.bulk([
    { expand: true, cwd: 'source', src: ['**'], dest: 'source'}
]);
archive.finalize();
89
commadelimited

Je ne prétends pas montrer quelque chose de nouveau, je veux simplement résumer les solutions ci-dessus pour ceux qui aiment utiliser les fonctions Promise dans leur code (comme moi).

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();
  });
}

J'espère que ça va aider quelqu'un;)

11
D.Dimitrioglo

Pour inclure tous les fichiers et répertoires:

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

Il utilise node-glob ( https://github.com/isaacs/node-glob ) en dessous, ainsi toute expression correspondante compatible avec cela fonctionnera.

10
Sam Ghaderyan

Archive.bulk est maintenant obsolète, la nouvelle méthode à utiliser est 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();
9
caiocpricci2

Utilisez l'API child_process native du nœud pour accomplir cela.

Pas besoin de bibliothèques tierces. Deux lignes de code. 

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
});

J'utilise l'API synchrone. Vous pouvez utiliser child_process.exec(path, options, callback) si vous avez besoin d'async. Il y a beaucoup plus d'options que de simplement spécifier le CWD pour affiner vos demandes. Voir exec/execSync docs.

4
Govind Rai

Adm-Zip a des problèmes lors de la compression d'une archive existante https://github.com/cthackers/adm-Zip/issues/64 ainsi que de la corruption lors de la compression des fichiers binaires.

J'ai également rencontré des problèmes de corruption de compression avec node-Zip https://github.com/daraosn/node-Zip/issues/4

node-archiver est le seul qui semble bien compresser, mais il n'a pas de fonctionnalité de décompression.

3
Xiaoxin

Pour diriger le résultat vers l'objet de réponse (scénarios dans lesquels il est nécessaire de télécharger le zip plutôt que de le stocker localement) 

 archive.pipe(res);

Les astuces de Sam pour accéder au contenu du répertoire ont fonctionné pour moi. 

src: ["**/*"]
3
Raf

Ceci est une autre bibliothèque qui ferme le dossier sur une ligne: Zip-local

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

zipper.sync.Zip("./hello/world/").compress().save("pack.Zip");
1
Dreams

J'ai trouvé cette petite bibliothèque qui contient tout ce dont vous avez besoin. 

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

0

Vous pouvez essayer de manière simple:

Installez Zip-dir:

npm install Zip-dir

et l'utiliser

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

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

    });
0
Harsha Biyani