我尝试通过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
})
});
. . . .
有什么建议吗?标题?
答案 0 :(得分:2)
此处的问题(及其解决方案)隐藏在http-browserify文档中。首先,您需要了解有关browserify的一些事项:
考虑到这一点,您使用至少三个具有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只接受Stream
和string
输入,所以当你将响应传递给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
});
});