我想从互联网下载一个zip文件,并在内存中解压,而不保存到临时文件.我该怎么做?

以下是我try 过的:

var url = 'http://bdn-ak.bloomberg.com/precanned/Comdty_Calendar_Spread_Option_20120428.txt.zip';

var request = require('request'), fs = require('fs'), zlib = require('zlib');

  request.get(url, function(err, res, file) {
     if(err) throw err;
     zlib.unzip(file, function(err, txt) {
        if(err) throw err;
        console.log(txt.toString()); //outputs nothing
     });
  });

[编辑]

var ZipEntry = require('adm-zip/zipEntry');
request.get(url, function(err, res, zipFile) {
        if(err) throw err;
        var zip = new ZipEntry();
        zip.setCompressedData(new Buffer(zipFile.toString('utf-8')));
        var text = zip.getData();
        console.log(text.toString()); // fails
    });

推荐答案

你需要一个能处理缓冲区的库.adm-zip的最新版本可以:

npm install adm-zip

我的解决方案使用http.get方法,因为它返回缓冲区块.

代码:

var file_url = 'http://notepad-plus-plus.org/repository/7.x/7.6/npp.7.6.bin.x64.zip';

var AdmZip = require('adm-zip');
var http = require('http');

http.get(file_url, function(res) {
  var data = [], dataLen = 0; 

  res.on('data', function(chunk) {
    data.push(chunk);
    dataLen += chunk.length;

  }).on('end', function() {
    var buf = Buffer.alloc(dataLen);

    for (var i = 0, len = data.length, pos = 0; i < len; i++) { 
      data[i].copy(buf, pos); 
      pos += data[i].length; 
    } 

    var zip = new AdmZip(buf);
    var zipEntries = zip.getEntries();
    console.log(zipEntries.length)

    for (var i = 0; i < zipEntries.length; i++) {
      if (zipEntries[i].entryName.match(/readme/))
        console.log(zip.readAsText(zipEntries[i]));
    }
  });
});

其 idea 是创建一个缓冲区数组,并在最后将它们连接成一个新的缓冲区.这是因为缓冲区无法调整大小.

Update

这是一个更简单的解决方案,通过在选项中设置encoding: null,使用request模块在缓冲区中获得响应.它还会自动执行重定向和解析http/https.

var file_url = 'https://github.com/mihaifm/linq/releases/download/3.1.1/linq.js-3.1.1.zip';

var AdmZip = require('adm-zip');
var request = require('request');

request.get({url: file_url, encoding: null}, (err, res, body) => {
  var zip = new AdmZip(body);
  var zipEntries = zip.getEntries();
  console.log(zipEntries.length);

  zipEntries.forEach((entry) => {
    if (entry.entryName.match(/readme/i))
      console.log(zip.readAsText(entry));
  });
});

响应的body是一个可以直接传递到AdmZip的缓冲区,简化了整个过程.

Node.js相关问答推荐

使用NodeJS输出检索Base64图像的网络报废

带有apache Couch-db和Nano的推荐引擎:过滤特定用户的视图

Node.js中Redis的并发问题

Sass-TypeError:无法读取未定义的属性(正在读取';indexOf';)

FiRestore UPDATE方法引发错误:&Quot;错误:13内部:收到代码为1&Quot;的RST_STREAM

尽管 tsconfig 中提供了正确的路径,但仍出现找不到模块错误

如何在 require 方法中使用路径与node.js react ?

无法截取页面截图

Docker node_modules 文件夹上的 React 应用程序不可用

为什么 $or 在带有正则表达式的mongoose 中不能正常工作

用户与mongoose 的完美搭配

如何防止 node.js 中的内存泄漏?

`npm install` 以Killed结尾

Nodejs 随机免费 tcp 端口

Node.js 中空函数的简写

webpack css-loader 在外部样式表的 url() 引用中找不到图像

JavaScript 异步编程:promise 与生成器

如何在离线时安装 npm 包?

npm install 给出警告,npm audit fix 不起作用

Node.js 连接仅适用于本地主机