javascript 节点:通过请求下载 zip,Zip 已损坏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12029523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Node: Downloading a zip through Request, Zip being corrupted
提问by Hyman Franklin
I'm using the excellent Requestlibrary for downloading files in Node for a small command line tool I'm working on. Request works perfectly for pulling in a single file, no problems at all, but it's not working for ZIPs.
我正在使用优秀的Request库在 Node 中下载文件,用于我正在开发的一个小型命令行工具。Request 非常适合拉入单个文件,完全没有问题,但它不适用于 ZIP。
For example, I'm trying to download the Twitter Bootstraparchive, which is at the URL:
例如,我正在尝试下载位于以下 URL的Twitter Bootstrap存档:
http://twitter.github.com/bootstrap/assets/bootstrap.zip
The relevant part of the code is:
代码的相关部分是:
var fileUrl = "http://twitter.github.com/bootstrap/assets/bootstrap.zip";
var output = "bootstrap.zip";
request(fileUrl, function(err, resp, body) {
if(err) throw err;
fs.writeFile(output, body, function(err) {
console.log("file written!");
}
}
I've tried setting the encoding to "binary" too but no luck. The actual zip is ~74KB, but when downloaded through the above code it's ~134KB and on double clicking in Finder to extract it, I get the error:
我也尝试将编码设置为“二进制”,但没有运气。实际的 zip 是 ~74KB,但是当通过上面的代码下载时它是 ~134KB 并且在 Finder 中双击以提取它,我收到错误:
Unable to extract "bootstrap" into "nodetest" (Error 21 - Is a directory)
无法将“bootstrap”提取到“nodetest”中(错误 21 - 是目录)
I get the feeling this is an encoding issue but not sure where to go from here.
我觉得这是一个编码问题,但不确定从哪里开始。
回答by juandopazo
Yes, the problem is with encoding. When you wait for the whole transfer to finish body
is coerced to a string by default. You can tell request
to give you a Buffer
instead by setting the encoding
option to null
:
是的,问题在于编码。当您等待整个传输完成时body
,默认情况下会强制转换为字符串。你可以告诉request
给你Buffer
用,而不是设置encoding
选项null
:
var fileUrl = "http://twitter.github.com/bootstrap/assets/bootstrap.zip";
var output = "bootstrap.zip";
request({url: fileUrl, encoding: null}, function(err, resp, body) {
if(err) throw err;
fs.writeFile(output, body, function(err) {
console.log("file written!");
});
});
Another more elegant solution is to use pipe()
to point the response to a file writable stream:
另一个更优雅的解决方案是使用pipe()
将响应指向文件可写流:
request('http://twitter.github.com/bootstrap/assets/bootstrap.zip')
.pipe(fs.createWriteStream('bootstrap.zip'))
.on('close', function () {
console.log('File written!');
});
A one liner always wins :)
一个班轮总是赢:)
pipe()
returns the destination stream (the WriteStream in this case), so you can listen to its close
event to get notified when the file was written.
pipe()
返回目标流(在本例中为 WriteStream),因此您可以侦听其close
事件以在文件写入时获得通知。
回答by Flament Micka?l
I was searching about a function which request a zip and extract it without create any file inside my server, here is my TypeScript function, it use JSZIP moduleand Request:
我正在搜索一个请求 zip 并提取它而不在我的服务器中创建任何文件的函数,这是我的 TypeScript 函数,它使用JSZIP 模块和请求:
let bufs : any = [];
let buf : Uint8Array;
request
.get(url)
.on('end', () => {
buf = Buffer.concat(bufs);
JSZip.loadAsync(buf).then((zip) => {
// zip.files contains a list of file
// chheck JSZip documentation
// Example of getting a text file : zip.file("bla.txt").async("text").then....
}).catch((error) => {
console.log(error);
});
})
.on('error', (error) => {
console.log(error);
})
.on('data', (d) => {
bufs.push(d);
})