如何使用Node.js without using third-party libraries 下载文件?
我不需要任何特别的东西 . 我只想从给定的URL下载文件,然后将其保存到给定的目录中 .
19 回答
438
您可以创建HTTP GET 请求并将其 response 管道传输到可写文件流中:
var http = require('http');
var fs = require('fs');
var file = fs.createWriteStream("file.jpg");
var request = http.get("http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg", function(response) {
response.pipe(file);
});
function download(url, dest, callback) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function (response) {
response.pipe(file);
file.on('finish', function () {
file.close(callback); // close() is async, call callback after close completes.
});
file.on('error', function (err) {
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (callback)
callback(err.message);
});
});
}
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(要么)
function readApp(req,res) {
var file = req.fileName,
filePath = "/home/sony/Documents/docs/";
fs.exists(filePath, function(exists){
if (exists) {
res.writeHead(200, {
"Content-Type": "application/octet-stream",
"Content-Disposition" : "attachment; filename=" + file});
fs.createReadStream(filePath + file).pipe(res);
} else {
res.writeHead(400, {"Content-Type": "text/plain"});
res.end("ERROR File does NOT Exists.ipa");
}
});
}
2
路径:img类型:jpg随机uniqid
function resim(url) {
var http = require("http");
var fs = require("fs");
var sayi = Math.floor(Math.random()*10000000000);
var uzanti = ".jpg";
var file = fs.createWriteStream("img/"+sayi+uzanti);
var request = http.get(url, function(response) {
response.pipe(file);
});
return sayi+uzanti;
}
11
使用promise下载,解析可读流 . 添加额外的逻辑来处理重定向 .
var http = require('http');
var promise = require('bluebird');
var url = require('url');
var fs = require('fs');
var assert = require('assert');
function download(option) {
assert(option);
if (typeof option == 'string') {
option = url.parse(option);
}
return new promise(function(resolve, reject) {
var req = http.request(option, function(res) {
if (res.statusCode == 200) {
resolve(res);
} else {
if (res.statusCode === 301 && res.headers.location) {
resolve(download(res.headers.location));
} else {
reject(res.statusCode);
}
}
})
.on('error', function(e) {
reject(e);
})
.end();
});
}
download('http://localhost:8080/redirect')
.then(function(stream) {
try {
var writeStream = fs.createWriteStream('holyhigh.jpg');
stream.pipe(writeStream);
} catch(e) {
console.error(e);
}
});
419
function download(url, dest, cb) {
var request = http.get(url, function (response) {
const settings = {
flags: 'w',
encoding: 'utf8',
fd: null,
mode: 0o666,
autoClose: true
};
// response.pipe(fs.createWriteStream(dest, settings));
var file = fs.createWriteStream(dest, settings);
response.pipe(file);
file.on('finish', function () {
let okMsg = {
text: `File downloaded successfully`
}
cb(okMsg);
file.end();
});
}).on('error', function (err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
let errorMsg = {
text: `Error in file downloadin: ${err.message}`
}
if (cb) cb(errorMsg);
});
};
19 回答
您可以创建HTTP
GET
请求并将其response
管道传输到可写文件流中:如果要支持在命令行上收集信息(如指定目标文件或目录或URL),请查看类似Commander的内容 .
不要忘记处理错误!以下代码基于Augusto Roman的回答 .
正如Brandon Tilley所说,但具有适当的控制流程:
无需等待
finish
事件,天真的脚本可能会以不完整的文件结束 .Edit: 感谢@Augusto Roman指出应将
cb
传递给file.close
,而不是明确调用 .说到处理错误,它甚至可以更好地监听请求错误 . 我甚至通过检查响应代码来验证 . 这里仅认为200响应代码成功,但其他代码可能是好的 .
尽管此代码相对简单,但我建议使用request module,因为它处理了更多的协议(hello HTTPS!),
http
本身不支持这些协议 .这将是这样做的:
gfxmonk的答案在回调和
file.close()
完成之间的数据竞争非常紧张 .file.close()
实际上是在完成关闭时调用的回调 . 否则,立即使用该文件可能会失败(很少!) .完整的解决方案是:
无需等待完成事件,天真的脚本可能会以不完整的文件结束 . 如果不通过关闭安排
cb
回调,您可能会在访问文件和实际准备好的文件之间进行竞争 .对于那些寻找基于es6风格承诺的方式,我想它会是这样的:
超时解决方案,防止内存泄漏:
以下代码基于Brandon Tilley的答案:
当你收到错误时不要创建文件,并且在X secondes之后优先使用超时来关闭你的请求 .
也许node.js发生了变化,但似乎其他解决方案存在一些问题(使用节点v8.1.2):
您无需在
finish
事件中调用file.close()
. 默认情况下,fs.createWriteStream
设置为autoClose:https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options应该在出错时调用
file.close()
. 删除文件时可能不需要这样做(unlink()
),但通常是:https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200
上未删除临时文件不建议使用回调的
fs.unlink()
(输出警告)如果
dest
文件存在;它被覆盖了以下是处理这些问题的修改后的解决方案(使用ES6和承诺) .
Vince Yuan的代码很棒,但似乎有些不对劲 .
你可以用https://github.com/douzi8/ajax-request#download
如果您使用快速使用res.download()方法 . 否则fs模块使用 .
(要么)
路径:img类型:jpg随机uniqid
使用promise下载,解析可读流 . 添加额外的逻辑来处理重定向 .
如果没有库,只需指出它就可能是错误的 . 以下是一些:
无法处理http重定向,就像这个url https://calibre-ebook.com/dist/portable这是二进制的 .
http模块无法https url,你会得到
Protocol "https:" not supported.
我的建议在这里:
调用系统工具,如
wget
或curl
使用像node-wget-promise这样的工具也很简单 .
var wget = require('node-wget-promise'); wget('http://nodejs.org/images/logo.svg');
您可以尝试使用
res.redirect
到https文件下载URL,然后它将下载该文件 .喜欢:
res.redirect('https//static.file.com/file.txt');
我们可以使用下载节点模块,它非常简单,请参考下面的https://www.npmjs.com/package/download