Le moyen le plus simple de télécharger et de décompresser des fichiers sur Node.js sur plusieurs plates-formes?

Il suffit de chercher une solution simple pour télécharger et décompresser les fichiers .zip ou .tar.gz dans Node.js sur n’importe quel système d’exploitation.

Je ne sais pas si cela est intégré ou je dois utiliser une bibliothèque séparée. Des idées? Vous cherchez juste quelques lignes de code alors quand le prochain fichier zip vient que je veux télécharger dans le nœud, c’est une évidence. Sentez-vous que cela devrait être facile et / ou intégré, mais je ne trouve rien. Merci!

Commander adm-zip .

ADM-ZIP est une implémentation purement JavaScript pour la compression des données zip pour NodeJS.

La bibliothèque vous permet de:

  • décompresser les fichiers zip directement sur le disque ou les tampons en mémoire
  • compresser des fichiers et les stocker sur disque au format .zip ou dans des tampons compressés
  • mettre à jour le contenu de / append de nouveaux fichiers / supprimer des fichiers existants .zip

Node prend en charge gzip et deflate via le module zlib :

 var zlib = require('zlib'); zlib.gunzip(gzipBuffer, function(err, result) { if(err) return console.error(err); console.log(result); }); 

Edit: Vous pouvez même Gunzip les données directement via eg Gunzip (à l’aide de request ):

 var request = require('request'), zlib = require('zlib'), fs = require('fs'), out = fs.createWriteStream('out'); // Fetch http://example.com/foo.gz, gunzip it and store the results in 'out' request('http://example.com/foo.gz').pipe(zlib.createGunzip()).pipe(out); 

Pour les archives tar, il existe le module tar Isaacs, utilisé par npm.

Edit 2: réponse mise à jour car zlib ne supporte pas le format zip . Cela ne fonctionnera que pour gzip .

C’est 2017 (le 26 octobre, pour être exact).

Pour une technologie ancienne et omniprésente telle que la décompression, je m’attendrais à ce qu’il existe une bibliothèque de décompression node.js assez populaire et mature qui soit “stagnante” et “non maintenue” car elle est “complète”.

Cependant, la plupart des bibliothèques semblent être complètement horribles ou avoir commis récemment comme il y a quelques mois. C’est assez préoccupant … j’ai donc parcouru plusieurs bibliothèques de décompression, lu leurs documents et essayé leurs exemples pour essayer de comprendre WTF. Par exemple, j’ai essayé ceux-ci:

  • thejoshwolfe / yauzl
  • antelle / node-stream-zip
  • ZJONSSON / node-unzipper
  • EvanOxfeld / node-unzip
  • Stuk / jszip
  • kriskowal / zip

Top Recommandation: yauzl

Fonctionne parfaitement pour les fichiers complètement téléchargés. Pas aussi bien pour le streaming.

Bien documenté. Fonctionne bien. Logique.

2ème choix: node-stream-zip

antelle- node-stream-zip semble être le meilleur

Installer:

 npm install --save node-stream-zip 

Usage:

 'use ssortingct'; var StreamZip = require('node-stream-zip'); var zip = new StreamZip({ file: './example.zip' , storeEnsortinges: true }); zip.on('error', function (err) { console.error('[ERROR]', err); }); zip.on('ready', function () { console.log('All ensortinges read: ' + zip.ensortingesCount); //console.log(zip.ensortinges()); }); zip.on('entry', function (entry) { var pathname = path.resolve('./temp', entry.name); if (/\.\./.test(path.relative('./temp', pathname))) { console.warn("[zip warn]: ignoring maliciously crafted paths in zip file:", entry.name); return; } if ('/' === entry.name[entry.name.length - 1]) { console.log('[DIR]', entry.name); return; } console.log('[FILE]', entry.name); zip.stream(entry.name, function (err, stream) { if (err) { console.error('Error:', err.toSsortingng()); return; } stream.on('error', function (err) { console.log('[ERROR]', err); return; }); // example: print contents to screen //stream.pipe(process.stdout); // example: save contents to file mkdirp(path.dirname(pathname, function (err) { stream.pipe(fs.createWriteStream(pathname)); }); }); }); 

Avertissement de sécurité :

Vous ne savez pas si cela vérifie entry.name pour les chemins conçus de manière malveillante qui seraient résolus de manière incorrecte (tels que ../../../foo ou /etc/passwd ).

Vous pouvez facilement vérifier cela vous-même en comparant /\.\./.test(path.relative('./to/dir', path.resolve('./to/dir', entry.name))) .

Avantages : (Pourquoi est-ce que je pense que c’est le meilleur?)

  • peut décompresser des fichiers normaux (peut-être pas des plus fous avec des extensions étranges)
  • peut diffuser
  • semble ne pas avoir à charger le zip entier pour lire les entrées
  • a des exemples en JavaScript normal (non compilé)
  • n’inclut pas l’évier de la cuisine (c.-à-d. chargement de l’url, couches S3 ou db)
  • utilise du code existant d’une bibliothèque populaire
  • n’a pas trop hipster ou ninja-foo insensé dans le code

Contre :

  • Avale des erreurs comme un hippopotame affamé
  • Lance des chaînes au lieu d’erreurs (pas de traces de stack)
  • zip.extract() ne semble pas fonctionner (j’ai donc utilisé zip.stream() dans mon exemple)

Finaliste: node-unzipper

Installer:

 npm install --save unzipper 

Usage:

 'use ssortingct'; var fs = require('fs'); var unzipper = require('unzipper'); fs.createReadStream('./example.zip') .pipe(unzipper.Parse()) .on('entry', function (entry) { var fileName = entry.path; var type = entry.type; // 'Directory' or 'File' console.log(); if (/\/$/.test(fileName)) { console.log('[DIR]', fileName, type); return; } console.log('[FILE]', fileName, type); // TODO: probably also needs the security check entry.pipe(process.stdout/*fs.createWriteStream('output/path')*/); // NOTE: To ignore use entry.autodrain() instead of entry.pipe() }); 

Avantages :

  • Semble fonctionner de manière similaire à node-stream-zip , mais moins de contrôle
  • Une fourchette de unzip plus fonctionnelle
  • Semble fonctionner en série plutôt qu’en parallèle

Contre :

  • La cuisine coulera beaucoup? Juste inclut une tonne de choses qui ne sont pas liées à la décompression
  • Lit tout le fichier (par morceau, ce qui est bien), pas seulement des recherches aléatoires

yauzl est une bibliothèque robuste pour la décompression. Principes de conception:

  • Suivez les spécifications. Ne pas rechercher les en-têtes de fichiers locaux. Lisez le répertoire central des métadonnées de fichier.
  • Ne bloquez pas le thread JavaScript. Utilisez et fournissez des API asynchrones.
  • Gardez la mémoire sous contrôle. N’essayez pas de mettre en mémoire tampon des fichiers entiers dans la RAM.
  • Ne jamais tomber en panne (si utilisé correctement). Ne laissez pas les fichiers zip malformés réduire les applications clientes qui tentent de détecter les erreurs.
  • Saisissez les entrées de noms de fichiers non sécurisés. Une entrée de fichier zip génère une erreur si son nom de fichier commence par “/” ou / [A-Za-z]: // ou s’il contient “..” des segments de chemin ou “\” (selon la spécification).

A présent une couverture de test de 97%.

J’ai essayé quelques-unes des bibliothèques de décompression de nodejs, y compris adm-zip et unzip, puis installé sur extract-zip qui est un wrapper autour de yauzl. Semble le plus simple à mettre en œuvre.

https://www.npmjs.com/package/extract-zip

 var extract = require('extract-zip') extract(zipfile, { dir: outputPath }, function (err) { // handle err }) 

J’attendais cela depuis longtemps et je n’ai trouvé aucun exemple de travail simple, mais sur la base de ces réponses, j’ai créé la fonction downloadAndUnzip() .

L’utilisation est assez simple:

 downloadAndUnzip('http://your-domain.com/archive.zip', 'yourfile.xml') .then(function (data) { console.log(data); // unzipped content of yourfile.xml in root of archive.zip }) .catch(function (err) { console.error(err); }); 

Et voici la déclaration:

 var AdmZip = require('adm-zip'); var request = require('request'); var downloadAndUnzip = function (url, fileName) { /** * Download a file * * @param url */ var download = function (url) { return new Promise(function (resolve, reject) { request({ url: url, method: 'GET', encoding: null }, function (err, response, body) { if (err) { return reject(err); } resolve(body); }); }); }; /** * Unzip a Buffer * * @param buffer * @returns {Promise} */ var unzip = function (buffer) { return new Promise(function (resolve, reject) { var resolved = false; var zip = new AdmZip(buffer); var zipEnsortinges = zip.getEnsortinges(); // an array of ZipEntry records zipEnsortinges.forEach(function (zipEntry) { if (zipEntry.entryName == fileName) { resolved = true; resolve(zipEntry.getData().toSsortingng('utf8')); } }); if (!resolved) { reject(new Error('No file found in archive: ' + fileName)); } }); }; return download(url) .then(unzip); }; 

Un autre exemple de travail:

 var zlib = require('zlib'); var tar = require('tar'); var ftp = require('ftp'); var files = []; var conn = new ftp(); conn.on('connect', function(e) { conn.auth(function(e) { if (e) { throw e; } conn.get('/tz/tzdata-latest.tar.gz', function(e, stream) { stream.on('success', function() { conn.end(); console.log("Processing files ..."); for (var name in files) { var file = files[name]; console.log("filename: " + name); console.log(file); } console.log("OK") }); stream.on('error', function(e) { console.log('ERROR during get(): ' + e); conn.end(); }); console.log("Reading ..."); stream .pipe(zlib.createGunzip()) .pipe(tar.Parse()) .on("entry", function (e) { var filename = e.props["path"]; console.log("filename:" + filename); if( files[filename] == null ) { files[filename] = ""; } e.on("data", function (c) { files[filename] += c.toSsortingng(); }) }); }); }); }) .connect(21, "ftp.iana.org"); 

J’ai trouvé le succès avec ce qui suit, travaille avec .zip
(Simplifié ici pour la publication: pas de vérification des erreurs et il suffit de décompresser tous les fichiers dans le dossier actuel)

 function DownloadAndUnzip(URL){ var unzip = require('unzip'); var http = require('http'); var request = http.get(URL, function(response) { response.pipe(unzip.Extract({path:'./'})) }); } 

Vous pouvez simplement extraire les fichiers zip existants également en utilisant “unzip”. Cela fonctionnera pour tous les fichiers de taille.

 fs.createReadStream(filePath).pipe(unzip.Extract({path:moveIntoFolder})).on('close', function(){ //To do after unzip callback(); });