Nous sommes en 2017 (le 26 octobre, pour être exact).
Pour une technologie ancienne et omniprésente comme unzip, je m'attendrais à ce qu'il existe une bibliothèque unzip node.js assez populaire et mature qui soit "stagnante" et "non maintenue" parce qu'elle est "complète".
Cependant, la plupart des bibliothèques semblent soit être complètement terribles, soit avoir fait l'objet de modifications il y a seulement quelques mois. C'est assez inquiétant... j'ai donc passé en revue plusieurs bibliothèques de dézippage, lu leur documentation et essayé leurs exemples pour essayer de comprendre ce qui se passe. Par exemple, j'ai essayé celles-ci :
Mise à jour 2020 : Je ne l'ai pas encore essayé, mais il y a aussi archiveur
Meilleure recommandation : yauzl
Fonctionne très bien pour un fichier entièrement téléchargé. Pas aussi bien pour le streaming.
Bien documenté. Fonctionne bien. C'est logique.
2ème choix : node-stream-zip
d'antelle node-stream-zip
semble être le meilleur
Installez :
npm install --save node-stream-zip
Uso:
'use strict';
var fs = require('fs');
var StreamZip = require('node-stream-zip');
var zip = new StreamZip({
file: './example.zip'
, storeEntries: true
});
zip.on('error', function (err) { console.error('[ERROR]', err); });
zip.on('ready', function () {
console.log('All entries read: ' + zip.entriesCount);
//console.log(zip.entries());
});
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.toString()); 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
fs.mkdir(
path.dirname(pathname),
{ recursive: true },
function (err) {
stream.pipe(fs.createWriteStream(pathname));
}
);
});
});
Avertissement de sécurité :
Je ne suis pas sûr que ce soit le cas. entry.name
pour les chemins d'accès malveillants qui ne seraient pas résolus correctement (tels que ../../../foo
o /etc/passwd
).
Vous pouvez facilement le vérifier vous-même en comparant /\.\./.test(path.relative('./to/dir', path.resolve('./to/dir', entry.name)))
.
Pour (Pourquoi est-ce que je pense que c'est le meilleur ?)
- peut décompresser des fichiers normaux (peut-être pas des fichiers fous avec des extensions bizarres)
- peut diffuser
- semble ne pas devoir charger tout le zip pour lire les entrées
- a des exemples en JavaScript normal (non compilé)
- n'inclut pas l'évier de cuisine (c'est-à-dire le chargement d'url, S3, ou les couches de db)
- utilise du code existant d'une bibliothèque populaire
- n'a pas trop de hipster ou de ninja-foo insensés dans le code
Cons :
- Les erreurs des hirondelles comme un hippopotame affamé
- Lance des chaînes au lieu d'erreurs (pas de traces de pile)
-
zip.extract()
ne semble pas fonctionner (c'est pourquoi j'ai utilisé l'option zip.stream()
dans mon exemple)
Deuxième place : node-unzipper
Installez :
npm install --save unzipper
Uso:
'use strict';
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()
});
Pour :
- Il semble fonctionner de manière similaire à
node-stream-zip
mais moins de contrôle
- Une bifurcation plus fonctionnelle de
unzip
- Semble fonctionner en série plutôt qu'en parallèle
Cons :
- Un évier de cuisine ? Il inclut juste une tonne de choses qui ne sont pas liées à la décompression.
- Lit l'ensemble du fichier (par morceaux, ce qui est bien), et pas seulement les recherches aléatoires.