如何在不使用第三方库的情况下使用Node.js下载文件?
我不需要什么特别的东西。我只想从给定的URL下载文件,然后将其保存到给定的目录。
如何在不使用第三方库的情况下使用Node.js下载文件?
我不需要什么特别的东西。我只想从给定的URL下载文件,然后将其保存到给定的目录。
当前回答
Gfxmonk的答案在回调和file.close()完成之间有一个非常紧张的数据竞赛。File.close()实际上接受一个回调函数,该函数在close完成时被调用。否则,立即使用文件可能会失败(非常罕见!)。
一个完整的解决方案是:
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.
});
});
}
如果不等待finish事件,幼稚的脚本可能最终得到一个不完整的文件。如果不通过close调度cb回调,您可能会在访问文件和文件实际准备就绪之间出现竞争。
其他回答
如果您正在使用express,请使用res.download()方法。否则使用fs模块。
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(or)
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");
}
});
}
说到处理错误,监听请求错误甚至更好。我甚至会通过检查响应代码来验证。这里认为只有200个响应代码成功,但其他代码可能很好。
const fs = require('fs');
const http = require('http');
const download = (url, dest, cb) => {
const file = fs.createWriteStream(dest);
const request = http.get(url, (response) => {
// check if response is success
if (response.statusCode !== 200) {
return cb('Response status was ' + response.statusCode);
}
response.pipe(file);
});
// close() is async, call cb after close completes
file.on('finish', () => file.close(cb));
// check for request error too
request.on('error', (err) => {
fs.unlink(dest, () => cb(err.message)); // delete the (partial) file and then return the error
});
file.on('error', (err) => { // Handle errors
fs.unlink(dest, () => cb(err.message)); // delete the (partial) file and then return the error
});
};
尽管这段代码相对简单,但我建议使用request模块,因为它处理更多http不支持的协议(你好,HTTPS!)。
可以这样做:
const fs = require('fs');
const request = require('request');
const download = (url, dest, cb) => {
const file = fs.createWriteStream(dest);
const sendReq = request.get(url);
// verify response code
sendReq.on('response', (response) => {
if (response.statusCode !== 200) {
return cb('Response status was ' + response.statusCode);
}
sendReq.pipe(file);
});
// close() is async, call cb after close completes
file.on('finish', () => file.close(cb));
// check for request errors
sendReq.on('error', (err) => {
fs.unlink(dest, () => cb(err.message)); // delete the (partial) file and then return the error
});
file.on('error', (err) => { // Handle errors
fs.unlink(dest, () => cb(err.message)); // delete the (partial) file and then return the error
});
};
编辑:
要使它与https兼容,请更改
const http = require('http');
to
const http = require('https');
您可以尝试使用res.redirect到https文件下载url,然后它将下载文件。
如:res.redirect(“https / / static.file.com/file.txt”);
我更喜欢request(),因为你可以同时使用http和https。
request('http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg')
.pipe(fs.createWriteStream('cat.jpg'))
2022年底编辑:
Node v18及以上版本自带自带的Fetch API支持。使用它。
最初的回答:
对于支持承诺的节点,与其他答案相比,一个简单的(部分)Fetch API的Node shim只需要少量额外的代码:
const fs = require(`fs`);
const http = require(`http`);
const https = require(`https`);
module.exports = function fetch(url) {
return new Promise((resolve, reject) => {
const data = [];
const client = url.startsWith("https") ? https : http;
client
.request(url, (res) => {
res.on(`data`, (chunk) => data.push(chunk));
res.on(`end`, () => {
const asBytes = Buffer.concat(data);
const asString = asBytes.toString(`utf8`);
resolve({
arrayBuffer: async () => asBytes,
json: async () => JSON.parse(asString),
text: async () => asString,
});
});
res.on(`error`, (e) => reject(e));
})
.end();
});
};
你可以用它来做任何你需要的事情,使用普通的fetch语法:
const fetch = require(`./tiny-fetch.js`);
fetch(`https://placekitten.com/200/300`)
.then(res => res.arrayBuffer())
.then(bytes => fs.writeFileSync(`kitten.jpg`, bytes))
.catch(e => console.error(e));
fetch(`https://jsonplaceholder.typicode.com/todos/1`)
.then(res => res.json())
.then(obj => console.log(obj))
.catch(e => console.error(e));
// etc.