Comment télécharger et décompresser un fichier zip dans la mémoire en NodeJs?
Je veux télécharger un fichier zip à partir de l'internet et décompressez-le dans la mémoire sans l'enregistrer dans un fichier temporaire. Comment puis-je faire cela?
Voici ce que j'ai essayé:
var url = 'http://bdn-ak.bloomberg.com/precanned/Comdty_Calendar_Spread_Option_20120428.txt.zip';
var request = require('request'), fs = require('fs'), zlib = require('zlib');
request.get(url, function(err, res, file) {
if(err) throw err;
zlib.unzip(file, function(err, txt) {
if(err) throw err;
console.log(txt.toString()); //outputs nothing
});
});
[MODIFIER]
Comme, a suggéré, j'ai essayé d'utiliser le sma-zip bibliothèque et je ne peux toujours pas faire ce travail:
var ZipEntry = require('adm-zip/zipEntry');
request.get(url, function(err, res, zipFile) {
if(err) throw err;
var zip = new ZipEntry();
zip.setCompressedData(new Buffer(zipFile.toString('utf-8')));
var text = zip.getData();
console.log(text.toString()); //fails
});
- Notez bien que
zlib
ne gère pas les zip format de fichier, il ne gère que gzip et deflate formats. Lezlib.unzip
fonction est faussement nommé, car il ne décompresse gzip et deflate formats. Vous avez besoin d'un format zip bibliothèque. - Cette zipfile semble prometteuse github.com/springmeyer/node-zipfile/blob/master/README.md
- En fait, zlib occupe également de la
zlib
format (qui à son tour utilise dégonfler). Mais c'est totalement hors de propos ici, donc +1 🙂 - Double Possible. stackoverflow.com/questions/2095697/...
- Votre deuxième exemple de la modification à l'aide de
request.get
qui appelle automatiquementtoString()
sur les données renvoyées. Maisadam-zip
nécessite unBuffer
pas unString
. Utilisationrequest({url: url, encoding: null}, function(err, res, zipFile) { ...
au lieu derequest.get
de fairerequest
retour d'unBuffer
. (Bien que quand je l'ai fait j'ai eu unCRC32 checksum failed
erreur 🙁 Vous devriez vraiment juste sauterrequest
et l'utilisation mihai la réponse ci-dessous.
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin d'une bibliothèque qui peut gérer les tampons. La dernière version de
adm-zip
fera:Ma solution utilise la
http.get
méthode, car elle renvoie Tampon morceaux.Code:
L'idée est de créer une gamme de tampons et les concaténer en un seul à la fin. Cela est dû au fait que les tampons ne peuvent pas être redimensionnées.
Mise à jour
C'est une solution plus simple qui utilise le
request
module pour obtenir la réponse dans un tampon, par la mise enencoding: null
dans les options. Il suit également les redirections et les résout http/https automatiquement.La
body
de la réponse est une mémoire tampon qui peut être transmis directement àAdmZip
, de simplifier l'ensemble du processus.npm install adm-zip
ne fonctionnera pas parce que seule la dernière version sur github prend en charge les tampons.require('restler-q').get(URL).then
, qui permettra de télécharger l'intégralité de la chose dans la mémoire, et d'écrire le tout sur le disque. Pas aussi efficace, mais chunking solutions ne fonctionnent pas pour moi non plus...axios
de présentation de la demande, qui a la possibilité de télécharger l'ensemble de la chose comme un ArrayBuffer si vous définissez responseType pour'arraybuffer'
. Ensuite, vous pouvez passer à laresponse.data
directement à AdmZiphttp.get
ne pas suivre les redirections. Il n'est pas lié à la décompressionMalheureusement vous ne pouvez pas pipe le flux de réponse dans le décompresser d'emploi en tant que nœud
zlib
lib permet de le faire, vous disposez de cache et d'attendre la fin de la réponse. Je vous suggère de tuyau de la réponse à unefs
flux dans le cas de gros fichiers, sinon vous aurez à remplir pleinement votre mémoire en un clin d'oeil!Je ne comprends pas complètement ce que vous essayez de faire, mais à mon humble avis c'est la meilleure approche. Vous devriez garder vos données dans la mémoire que le temps vous en avez vraiment besoin, puis ruisseau de la csv analyseur.
Si vous voulez conserver vos données dans la mémoire vous pouvez remplacer le csv analyseur méthode
fromPath
avecfrom
qui prend un tampon en lieu et getData retour directementunzipped
Vous pouvez utiliser le
AMDZip
(comme @mihai dit) au lieu denode-zip
, juste attention carAMDZip
n'est pas encore publié au mnp si vous avez besoin de:N. B. Hypothèse: le fichier zip contient un seul fichier
Si vous êtes sous MacOS ou Linux, vous pouvez utiliser le
unzip
commande pour décompresser destdin
.Dans cet exemple, je suis en train de lire le fichier zip à partir du système de fichiers dans un
Buffer
objet, mais il fonctionneavec un fichier téléchargé ainsi:
Qui est en fait juste le nœud version du:
MODIFIER: Il est intéressant de noter que cela ne fonctionnera pas si l'entrée de la zip est trop gros pour être lu d'un coup, à partir de stdin. Si vous avez besoin de lire des fichiers plus gros, et votre fichier zip contient un seul fichier, vous pouvez utiliser funzip au lieu de
unzip
:Si votre fichier zip qui contient plusieurs fichiers (et le fichier que vous voulez n'est pas le premier) j'ai peur de dire que vous êtes hors de la chance. Décompressez besoin de chercher dans le
.zip
fichier depuis les fichiers zip sont juste un conteneur, et décompressez-le peut, il suffit de dézipper le dernier fichier. Dans ce cas, vous devez enregistrer le fichier temporaire (nœud-temp est très pratique).Il y a deux jours le module
node-zip
a été publiée, qui est un wrapper pour le JavaScript seule version de Zip: JSZip.var fs = require('fs);
var décompresser = require('unzip');
//unzip a.zip de dictionnaire
fs.createReadStream('./path/a.zip').pipe(décompressez-le.Extrait de({ path: './chemin/' }));
J'ai utilisé décompressez le module, et cela a fonctionné .