本文翻译自:How to download a file with Node.js (without using third-party libraries)?
How do I download a file with Node.js without using third-party libraries ? 如何在不使用第三方库的情况下使用 Node.js下载文件?
I don't need anything special. 我不需要什么特别的东西。 I only want to download a file from a given URL, and then save it to a given directory. 我只想从给定的URL下载文件,然后将其保存到给定的目录。
#1楼
参考:https://stackoom.com/question/o7QC/如何使用Node-js下载文件-不使用第三方库
#2楼
You can create an HTTP GET
request and pipe its response
into a writable file stream: 您可以创建HTTP GET
请求并将其response
通过管道response
到可写文件流中:
const http = require('http');
const fs = require('fs');
const file = fs.createWriteStream("file.jpg");
const request = http.get("http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg", function(response) {
response.pipe(file);
});
If you want to support gathering information on the command line--like specifying a target file or directory, or URL--check out something like Commander . 如果要支持在命令行上收集信息(例如指定目标文件或目录或URL),请查看Commander之类的内容 。
#3楼
As Michelle Tilley said, but with the appropriate control flow: 正如Michelle Tilley所说,但具有适当的控制流程:
var http = require('http');
var fs = require('fs');
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb);
});
});
}
Without waiting for the finish
event, naive scripts may end up with an incomplete file. 不等待finish
事件,天真的脚本可能会以不完整的文件结尾。
Edit: Thanks to @Augusto Roman for pointing out that cb
should be passed to file.close
, not called explicitly. 编辑:感谢@Augusto Roman指出cb
应该传递给file.close
,而不是显式调用。
#4楼
gfxmonk's answer has a very tight data race between the callback and the file.close()
completing. gfxmonk的答案在回调和file.close()
完成之间有非常紧密的数据竞争。 file.close()
actually takes a callback that is called when the close has completed. file.close()
实际上接受关闭完成时调用的回调。 Otherwise, immediate uses of the file may fail (very rarely!). 否则,该文件的立即使用可能会失败(非常罕见!)。
A complete solution is: 完整的解决方案是:
var http = require('http');
var fs = require('fs');
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
});
}
Without waiting for the finish event, naive scripts may end up with an incomplete file. 不等待完成事件,天真的脚本可能会以不完整的文件结尾。 Without scheduling the cb
callback via close, you may get a race between accessing the file and the file actually being ready. 如果不通过close安排cb
回调,则可能会在访问文件和实际准备好文件之间产生竞争。
#5楼
Don't forget to handle errors! 不要忘记处理错误! The following code is based on Augusto Roman's answer. 以下代码基于Augusto Roman的答案。
var http = require('http');
var fs = require('fs');
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
}).on('error', function(err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (cb) cb(err.message);
});
};
#6楼
Solution with timeout, prevent memory leak : 解决超时问题,防止内存泄漏:
The following code is based on Brandon Tilley's answer : 以下代码基于Brandon Tilley的答案:
var http = require('http'),
fs = require('fs');
var request = http.get("http://example12345.com/yourfile.html", function(response) {
if (response.statusCode === 200) {
var file = fs.createWriteStream("copy.html");
response.pipe(file);
}
// Add timeout.
request.setTimeout(12000, function () {
request.abort();
});
});
Don't make file when you get an error, and prefere to use timeout to close your request after X secondes. 出现错误时不要制作文件,而是希望在X秒后使用超时来关闭请求。