节点:通过请求下载zip,Zip已损坏

Jac*_*lin 12 javascript node.js

我正在使用优秀的Request库来下载Node中的文件,这是我正在使用的一个小命令行工具.请求完全适用于拉入单个文件,完全没有问题,但它不适用于ZIP.

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

http://twitter.github.com/bootstrap/assets/bootstrap.zip
Run Code Online (Sandbox Code Playgroud)

代码的相关部分是:

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!");
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试将编码设置为"二进制",但没有运气.实际的zip是~74KB,但是当通过上面的代码下载时它是~134KB并且双击Finder来提取它,我得到错误:

无法将"bootstrap"提取到"nodetest"中(错误21 - 是目录)

我觉得这是一个编码问题,但不知道从哪里开始.

jua*_*azo 44

是的,问题在于编码.等待整个传输完成时body默认强制转换为字符串.你可以告诉request给你Buffer用,而不是设置encoding选项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!");
  });
});
Run Code Online (Sandbox Code Playgroud)

另一个更优雅的解决方案是用于pipe()将响应指向文件可写流:

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

一个班轮总赢:)

pipe()返回目标流(在本例中为WriteStream),因此您可以监听其close事件以在写入文件时收到通知.

  • 通过侦听WriteStream上的`close`事件:`request(fileUrl).pipe(fs.createWriteStream(output)).on('close',function,当你在第二个选项中写入文件时,你仍然可以获得回调. (){console.log('File written!');});` (3认同)
  • `{encoding: null}` 结束了 10 个小时的调试。谢谢,这需要在谷歌搜索中排名 (2认同)