GUnzipping部分文件时如何避免zlib“意外的文件结束”?

时间:2015-11-25 21:47:12

标签: node.js zlib

我正在尝试在解压缩时读取gzip压缩文件的一部分,这样我就可以解析头部内容而无需读取不必要的字节。我之前使用fs.read()工作,同时传递选项只读取前500个字节,然后使用zlib.gunzip()解压缩内容,然后从二进制数据解析头。

这个工作正常,直到节点v5.0.0修补了一个错误,以确保zlib在截断的输入(https://github.com/nodejs/node/pull/2595)上抛出错误。

现在我从zlib收到以下错误。

Error: unexpected end of file

如何知道我在截断输入时没有抛出错误,我怎么能解压缩这个部分文件。我觉得流可能更容易,所以我写了以下内容。

var readStream = fs.createReadStream(file.path, {start: 0, end: 500});
var gunzip = zlib.createGunzip();

readStream.pipe(gunzip)
    .on('data', function(chunk) {
        console.log(parseBinaryHeader(chunk));
        console.log('got %d bytes of data', chunk.length);
    })
    .on('error', function (err) {
        console.log(err);
    })
    .on('end', function() {
        console.log('end');
    });

我的parseBinaryHeader()函数正在返回正确的标题内容,所以我知道它是解压缩但是当它到达输入结束时它仍然会抛出错误。我可以添加错误监听器来处理错误而不对它做任何事情,但这似乎并不理想。

有什么想法吗?

3 个答案:

答案 0 :(得分:6)

感谢所有建议。我还向节点存储库提交了一个问题,并获得了一些很好的反馈。这是最终为我工作的东西。

  • 将块大小设置为完整标题大小。
  • 将单个块写入解压缩流并立即暂停该流。
  • 处理解压缩的块。

例如

var bytesRead = 500;
var decompressStream = zlib.createGunzip()
    .on('data', function (chunk) {
        parseHeader(chunk);
        decompressStream.pause();
    }).on('error', function(err) {
        handleGunzipError(err, file, chunk);
    });

fs.createReadStream(file.path, {start: 0, end: bytesRead, chunkSize: bytesRead + 1})
    .on('data', function (chunk) {
        decompressStream.write(chunk);
    });

到目前为止,这一直在工作,并且允许我继续处理所有其他gunzip错误,因为pause()阻止解压缩流抛出“意外的文件结束”错误。

答案 1 :(得分:0)

我在尝试结束对 NodeJS Gzip 流的处理时遇到了同样的问题。我使用“buffer-peek-stream”来检查 gzip 流的标头 - 确定它实际上是一个 gzip 流。然后我解开流的前几兆字节 - 窥视该文件并确定 gzip 内容的 mime 类型。

这需要两次调用 zlib.createGunzip()

我发现,即使我创建了两个看似独立的 gunzip 转换实例,销毁第二个实例也会导致第一个实例抛出“意外的文件结尾”错误。即使第一个实例处于完全不同的环境中。

我的解决方法是在第一个实例上调用 .destroy() 来清理它,然后再创建第二个实例。

答案 2 :(得分:0)

我在使用 node v10.13.0 时遇到了这个错误。我升级到 v10.19.0 并修复了。