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

IT技术 javascript node.js
2021-02-23 01:27:40

我正在使用优秀的Request库在 Node 中下载文件,用于我正在开发的一个小型命令行工具。Request 非常适合拉入单个文件,完全没有问题,但它不适用于 ZIP。

例如,我正在尝试下载位于以下 URLTwitter Bootstrap存档:

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 - 是目录)

我觉得这是一个编码问题,但不确定从哪里开始。

2个回答

是的,问题在于编码。当您等待整个传输完成时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!");
  });
});

另一个更优雅的解决方案是使用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事件以在文件写入时获得通知。

{encoding: null}结束 10 小时的调试。谢谢,这需要在谷歌搜索中排名
2021-04-22 01:27:40
太好了谢谢!第一个被阻止的代码有效 :) 第二种方法更好,但是我需要一种在文件写入后运行回调的方法,这就是我选择第一个选项的原因。
2021-04-26 01:27:40
通过侦听closeWriteStream 上的事件,您仍然可以在第二个选项中写入文件时获得回调request(fileUrl).pipe(fs.createWriteStream(output)).on('close', function () {console.log('File written!');});
2021-05-01 01:27:40
那好多了!非常感谢你 :)
2021-05-09 01:27:40
它在request文档中。它说“如果为空,则主体作为缓冲区返回。” npmjs.com/package/request
2021-05-09 01:27:40

我正在搜索一个请求 zip 并提取它而不在我的服务器中创建任何文件的函数,这是我的 TypeScript 函数,它使用JSZIP module请求

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