【问题标题】:Node.js - Browserify: Error on parsing tar fileNode.js - Browserify:解析 tar 文件时出错
【发布时间】:2015-06-16 13:46:07
【问题描述】:

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

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

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

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

代码 sn-p 是这样的:

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

有什么建议吗?标头?

【问题讨论】:

    标签: javascript node.js parsing tar browserify


    【解决方案1】:

    这里的问题(及其解决方案)隐藏在 http-browserify 文档中。首先,你需要了解一些关于 browserify 的事情:

    • 浏览器环境与node.js环境不一样
    • Browserify 尽最大努力提供 node.js API,当您正在浏览的代码需要它们时,它们在浏览器中不存在
    • 替换的行为与 node.js 中的不完全相同,并且在浏览器中受到警告

    考虑到这一点,您至少要使用三个具有 browserify 重新实现/垫片的特定于节点的 API:网络连接、缓冲区和流。浏览器中的网络连接必然会被 XHR 调用所取代,这些调用在 Node [Node has Buffers] 中不存在的二进制数据周围有自己的语义。如果您查看here,您会注意到一个名为responseType 的选项;这设置了 XHR 调用的响应类型,必须这样做以确保您获取二进制数据而不是字符串数据。子栈建议使用ArrayBuffer;因为这必须在http.requestoptions对象上设置,所以你需要使用长格式请求格式而不是string-url格式:

    http.request({
        method: 'GET',
        hostname: 'www.site.com',
        path: '/path/to/request',
        responseType: 'arraybuffer' // note: lowercase
    }, function (res) {
        // ...
    });
    

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

    当您将响应类型设置为“arraybuffer”时,http-browserify 将emit chunks as Uint8Array。一旦你从http.request 得到一个Uint8Array,就会出现另一个问题:Stream API 只接受stringBuffer 作为输入,所以当你通过管道将响应发送到 tar 提取器流时,你'将收到TypeError: Invalid non-string/buffer chunk。在我看来,这似乎是stream-browserify 中的一个疏忽,它应该接受 Uint8Array 值以与浏览器化节点 API 的其他部分很好地配合。不过,您可以相当简单地自己解决它。浏览器 accepts a typed array 在构造函数中的 Buffer shim,因此您可以自己管道数据,手动将每个块转换为 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
        });
    });
    

    那么,您的代码应该如下所示:

    var req = http.request({
      method: 'GET',
      // Add your request hostname, path, etc. here
      responseType: 'arraybuffer'
    }, function(res){
      var tarExtractor = tar.extract();
    
      res.on('data', function (chunk) {
        tarExtractor.write(new Buffer(chunk));
      });
      res.on('end', tarExtractor.end.bind(tarExtractor));
      res.on('error', function (error) {
        console.log(error);
      });
    
      tarExtractor.on('entry', function(header, stream, callback) {
         console.log("File found " + header.name);
         stream.on('end', function() {
           console.log("<<EOF>>");
           callback();
         })
         stream.resume(); // This won't be necessary once you do something with the data
       })
    
      .on('finish', function(){
         console.log("All files parsed");
       });
    });
    

    【讨论】:

    • 嗯,工作非常顺利。将responseType 设置为arraybuffer,然后将其转换为Buffer 类型以与stream API 兼容,理解的关键是必须要鼓掌。谢谢! :) 接受
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    相关资源
    最近更新 更多