Node.js – Browserify:parsingtar文件时出错

我试图通过HTTP下载一个tar文件(非压缩的),并将其响应到tar-streamparsing器进行进一步处理。 当在terminal上执行时,这是完美的,没有任何错误。 对于在浏览器中使用的相同的东西, bundle.js文件是使用bundle.js生成的,并包含在HTML中。

tarstream包含3个文件。 浏览器在浏览器上执行代码时,会成功parsing2个条目,但会引发第三个条目的以下错误:

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

而使用相同的HTTP下载和parsing代码,tar文件在terminal上完整地下载和parsing。 为什么会发生这种情况?

代码片段是这样的:

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

有什么build议么? 头?

这里的问题(及其解决scheme)被藏在http-browserify文档中。 首先,您需要了解一些有关browserify的内容:

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

考虑到这一点,您至less使用了三个节点特定的API,它们具有浏览器重新实现/填充程序:networking连接,缓冲区和stream。 networking连接必要性在浏览器中被XHR调用replace,XHR调用有自己的在Node [Node has Buffers]中不存在的二进制数据的语义。 如果你看这里 ,你会注意到一个叫做responseType的选项。 这将设置XHR调用的响应types,必须完成该操作,以确保获取二进制数据而不是string数据。 Substackbuild议使用ArrayBuffer ; 由于必须在http.requestoptions对象上http.request ,所以需要使用长格式的请求格式,而不是stringurl格式:

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

请参阅xhr规范 ,了解responseType的有效值。 http-browserify 按原样传递它 。 在Node中,这个键将被忽略。

当您将响应types设置为“arraybuffer”时,http-browserify将以Uint8Array的forms发出块 。 从http.request获取Uint8Array后,会出现另一个问题: Stream API只接受stringBufferinput,因此当您将响应传递给tar提取器stream时,您将收到TypeError: Invalid non-string/buffer chunk 。 在我看来,这是stream-browserify browserify中的一个疏忽,它应该接受Uint8Array值,以便与browserified Node API的其他部分一致。 不过,你可以相当简单的解决它。 浏览器中的Buffer Shim在构造函数中接受一个types化数组 ,所以你可以自己pipe道数据,手动将每个数据块转换成一个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"); }); });