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

Node: Downloading a zip through Request, Zip being corrupted

本文关键字:zip 已损坏 下载 请求 节点      更新时间:2023-09-26

我正在为一个小型命令行工具使用优秀的Request库来下载Node中的文件。Request非常适合拉入单个文件,没有任何问题,但它不适用于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提取它时,我会得到错误:

无法将"引导程序"提取到"节点测试"中(错误21-是目录)

我觉得这是一个编码问题,但不知道该怎么办。

是的,问题出在编码上。当您等待整个传输完成时,默认情况下body被强制为字符串。您可以通过将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!");
  });
});

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

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

一句话总是赢的:)

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

我在搜索一个函数,该函数请求zip并提取它,而不在服务器内创建任何文件,这是我的TypeScript函数,它使用JSZIP模块和request:

let bufs : any = [];
let buf : Uint8Array;
request
    .get(url)
    .on('end', () => {
        buf = Buffer.concat(bufs);
        JSZip.loadAsync(buf).then((zip) => {
            // zip.files contains a list of file
            // chheck JSZip documentation
            // Example of getting a text file : zip.file("bla.txt").async("text").then....
        }).catch((error) => {
            console.log(error);
        });
    })
    .on('error', (error) => {
        console.log(error);
    })
    .on('data', (d) => {
        bufs.push(d);
    })