节点:通过请求,邮政编码下载一个压缩

我正在使用优秀的请求库来下载节点中的文件,以用于我正在处理的一个小命令行工具。 请求完美的拉动一个文件,完全没有问题,但它不适用于ZIP。

例如,我正在尝试下载Twitter Bootstrap存档,该存档位于URL:

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

代码的相关部分是:

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

我已经尝试将编码设置为“二进制”,但没有运气。 实际的zip是〜74KB,但是当通过上面的代码下载时,它是〜134KB,然后双击Finder来解压缩它,我得到错误:

无法提取“bootstrap”到“nodetest”(错误21 – 是一个目录)

我感觉这是一个编码问题,但不知道从哪里去。

是的,问题是编码。 当你等待整个传输完成时, body默认强制为一个string。 您可以通过将encoding选项设置为null来告诉request给你一个Buffer

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

另一个更优雅的解决scheme是使用pipe()将响应指向文件可写stream:

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

一个class轮总是赢得:)

pipe()返回目标stream(在这种情况下是WriteStream),所以你可以监听它的close事件,以便在写入文件的时候得到通知。