这里的问题(及其解决方案)隐藏在 http-browserify 文档中。首先,你需要了解一些关于 browserify 的事情:
- 浏览器环境与node.js环境不一样
- Browserify 尽最大努力提供 node.js API,当您正在浏览的代码需要它们时,它们在浏览器中不存在
- 替换的行为与 node.js 中的不完全相同,并且在浏览器中受到警告
考虑到这一点,您至少要使用三个具有 browserify 重新实现/垫片的特定于节点的 API:网络连接、缓冲区和流。浏览器中的网络连接必然会被 XHR 调用所取代,这些调用在 Node [Node has Buffers] 中不存在的二进制数据周围有自己的语义。如果您查看here,您会注意到一个名为responseType 的选项;这设置了 XHR 调用的响应类型,必须这样做以确保您获取二进制数据而不是字符串数据。子栈建议使用ArrayBuffer;因为这必须在http.request的options对象上设置,所以你需要使用长格式请求格式而不是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 只接受string 和Buffer 作为输入,所以当你通过管道将响应发送到 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");
});
});