Node.js - Browserify:解析tar文件时出错

时间:2015-06-16 13:46:08

标签: javascript node.js parsing tar browserify

我尝试通过HTTP下载tar文件(非压缩)并将其响应传递给tar-stream解析器以进行进一步处理。这在终端上执行时没有任何错误,因此非常有效。对于在浏览器上使用的相同内容,使用bundle.js生成browserify文件并包含在HTML中。

tar流包含3个文件。在浏览器上执行时,此浏览器化代码会成功解析2个条目,但会为第三个条目引发以下错误:

Error: Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?

使用相同的HTTP下载和解析代码,tar文件在终端上完全下载和解析而没有错误。为什么会这样??

代码段如下:

. . . .
var req = http.request(url, function(res){
  res.pipe(tar.extract())
  .on('entry', function(header, stream, callback) {
     console.log("File found " + header.name);
     stream.on('end', function() {
       console.log("<<EOF>>");
       callback();
     })
     stream.resume();
   })

  .on('finish', function(){
     console.log("All files parsed");
   })

  .on('error', function(error){
     console.log(error); //Raises the above mentioned error here
   })
});
. . . .

有什么建议吗?标题?

1 个答案:

答案 0 :(得分:2)

此处的问题(及其解决方案)隐藏在http-browserify文档中。首先,您需要了解有关browserify的一些事项:

  • 浏览器环境与node.js环境不同
  • 当您正在浏览的代码需要时,Browserify会尽力提供浏览器中不存在的node.js API
  • 替换的行为与node.js中的行为完全不同,并且在浏览器中有警告

考虑到这一点,您使用至少三个具有browserify重新实现/填充程序的特定于节点的API:网络连接,缓冲区和流。必要时,网络连接在浏览器中被XHR调用替换,XHR调用具有围绕Node [Node has Buffers]中不存在的二进制数据的自己的语义。如果你看here,你会发现一个名为responseType的选项;这将设置XHR调用的响应类型,必须这样做才能确保获得二进制数据而不是字符串数据。 Substack建议使用ArrayBuffer;因为必须在options的{​​{1}}对象上设置,所以需要使用长格式请求格式而不是string-url格式:

http.request

有关responseType的有效值,请参阅the xhr spec。 http-browserify passes it along as-is。在Node中,这个键将被忽略。

当您将响应类型设置为“arraybuffer”时,http-browserify将emit chunks as Uint8Array。从http.request({ method: 'GET', hostname: 'www.site.com', path: '/path/to/request', responseType: 'arraybuffer' // note: lowercase }, function (res) { // ... }); 收到Uint8Array后,又出现了另一个问题:http.request API只接受Streamstring输入,所以当你将响应传递给tar提取器流,您将收到Buffer。在我看来这是TypeError: Invalid non-string/buffer chunk的疏忽,它应该接受Uint8Array值与浏览器化Node API的其他部分很好地配合。不过,你可以相当简单地解决它。缓冲区在构造函数的浏览器accepts a typed array中进行填充,因此您可以自己管道数据,手动将每个块转换为stream-browserify

Buffer

那么,您的代码应该是这样的:

http.request(opts, function (res) {
    var tarExtractor = tar.extract();
    res.on('data', function (chunk) {
        tarExtractor.write(new Buffer(chunk));
    });
    res.on('end', function () {
        tarExtractor.end();
    });
    res.on('error', function (err) {
        // do something with your error
        // and clean up the tarExtractor instance if necessary
    });
});