遗憾的是,你无法像Node zlib
库允许的那样将响应流传输到解压作业中。你必须缓存并等待响应结束。我建议你在处理大文件时将响应导向fs
流,否则你的内存会很快被填满!
我不完全理解你试图做什么,但我认为这是最佳方法。你应该只在真正需要数据的时间将数据保存在内存中,然后流式传输到csv解析器。
如果你想在内存中保留所有数据,你可以使用替换csv解析器方法fromPath
的from
,它接受缓冲区,并在getData中直接返回unzipped
你可以使用AMDZip
代替node-zip
(如@mihai所说),但请注意AMDZip
尚未发布在npm上,因此你需要:
$ npm install git://github.com/cthackers/adm-zip.git
注意:假设zip文件只包含一个文件
var request = require('request'),
fs = require('fs'),
csv = require('csv')
NodeZip = require('node-zip')
function getData(tmpFolder, url, callback) {
var tempZipFilePath = tmpFolder + new Date().getTime() + Math.random()
var tempZipFileStream = fs.createWriteStream(tempZipFilePath)
request.get({
url: url,
encoding: null
}).on('end', function() {
fs.readFile(tempZipFilePath, 'base64', function (err, zipContent) {
var zip = new NodeZip(zipContent, { base64: true })
Object.keys(zip.files).forEach(function (filename) {
var tempFilePath = tmpFolder + new Date().getTime() + Math.random()
var unzipped = zip.files[filename].data
fs.writeFile(tempFilePath, unzipped, function (err) {
callback(err, tempFilePath)
})
})
})
}).pipe(tempZipFileStream)
}
getData('/tmp/', 'http://bdn-ak.bloomberg.com/precanned/Comdty_Calendar_Spread_Option_20120428.txt.zip', function (err, path) {
if (err) {
return console.error('error: %s' + err.message)
}
var metadata = []
csv().fromPath(path, {
delimiter: '|',
columns: true
}).transform(function (data){
if (data.NAME[0] === '#') {
metadata.push(data.NAME)
} else {
return data
}
}).on('data', function (data, index) {
console.log('#%d %s', index, JSON.stringify(data, null, ' '))
}).on('end',function (count) {
console.log('Metadata: %s', JSON.stringify(metadata, null, ' '))
console.log('Number of lines: %d', count)
}).on('error', function (error) {
console.error('csv parsing error: %s', error.message)
})
})
zlib
并不处理 zip 文件格式,它只处理 gzip 和 deflate 格式。zlib.unzip
函数的命名有误导性,因为它只能解压缩 gzip 和 deflate 格式。您需要一个支持 zip 格式的库。 - Dan D.zlib
格式(反过来使用deflate)。但这在这里完全无关紧要,所以+1 :-) - Cameronrequest.get
,这会自动调用返回数据的toString()
。但是adam-zip
需要的是Buffer
而不是String
。使用request({url: url, encoding: null}, function(err, res, zipFile) { ...
代替request.get
来让request
返回Buffer
。(尽管我这样做时出现了“CRC32 校验和失败”的错误 :( )你应该真的跳过request
直接使用下面 Mihai 的答案。 - Nathan Friedly