Nœud: Téléchargement d'un zip via la demande, Zip endommagé

J'utilise l'excellente bibliothèque de requêtes pour télécharger des fichiers dans Node pour un petit outil de ligne de commande sur lequel je travaille. La demande fonctionne parfaitement pour tirer un seul fichier, pas de problème, mais ça ne fonctionne pas pour les ZIP.

Par exemple, j'essaie de télécharger l'archive Twitter Bootstrap , qui se trouve sur l'URL:

http://twitter.github.com/bootstrap/assets/bootstrap.zip 

La partie pertinente du code est:

 var fileUrl = "http://twitter.github.com/bootstrap/assets/bootstrap.zip"; var output = "bootstrap.zip"; request(fileUrl, function(err, resp, body) { if(err) throw err; fs.writeFile(output, body, function(err) { console.log("file written!"); } } 

J'ai essayé de définir l'encodage à "binaire" aussi, mais pas de chance. Le zip réel est ~ 74KB, mais quand il est téléchargé par le code ci-dessus, il est ~ 134KB et en double-cliquant dans Finder pour l'extraire, j'obtiens l'erreur:

Impossible d'extraire "bootstrap" dans "nodetest" (erreur 21 – est un répertoire)

J'ai l'impression que c'est un problème d'encodage mais je ne sais pas d'où aller d'ici.

Oui, le problème concerne l'encodage. Lorsque vous attendez l'intégralité du transfert pour finir le body est contraint à une chaîne par défaut. Vous pouvez indiquer la request pour vous donner un Buffer place en définissant l'option de encoding comme null :

 var fileUrl = "http://twitter.github.com/bootstrap/assets/bootstrap.zip"; var output = "bootstrap.zip"; request({url: fileUrl, encoding: null}, function(err, resp, body) { if(err) throw err; fs.writeFile(output, body, function(err) { console.log("file written!"); }); }); 

Une autre solution plus élégante consiste à utiliser pipe() pour indiquer la réponse à un flux de fichiers inscriptibles:

 request('http://twitter.github.com/bootstrap/assets/bootstrap.zip') .pipe(fs.createWriteStream('bootstrap.zip')) .on('close', function () { console.log('File written!'); }); 

Un liner gagne toujours 🙂

pipe() renvoie le flux de destination (WriteStream dans ce cas), afin que vous puissiez écouter son événement close pour être averti lorsque le fichier a été écrit.