How do I download a file with Node.js without using third-party libraries?
I don\'t need anything special. I only want to download a file from a giv
Based on the other answers above and some subtle issues, here is my attempt.
fs.createWriteStream
if you get a 200 OK
status code. This reduces the amount of fs.unlink
commands required to tidy up temporary file handles.200 OK
we can still possibly reject
due to an EEXIST
file already exists.download
if you get a 301 Moved Permanently
or 302 Found (Moved Temporarily)
redirect following the link location provided in the header.download
was that they called resolve(download)
instead of download(...).then(() => resolve())
so the Promise
would return before the download actually finished. This way the nested chain of promises resolve in the correct order.const https = require('https');
const fs = require('fs');
/**
* Download a resource from `url` to `dest`.
* @param {string} url - Valid URL to attempt download of resource
* @param {string} dest - Valid path to save the file.
* @returns {Promise} - Returns asynchronously when successfully completed download
*/
function download(url, dest) {
return new Promise((resolve, reject) => {
const request = https.get(url, response => {
if (response.statusCode === 200) {
const file = fs.createWriteStream(dest, { flags: 'wx' });
file.on('finish', () => resolve());
file.on('error', err => {
file.close();
if (err.code === 'EEXIST') reject('File already exists');
else fs.unlink(dest, () => reject(err.message)); // Delete temp file
});
response.pipe(file);
} else if (response.statusCode === 302 || response.statusCode === 301) {
//Recursively follow redirects, only a 200 will resolve.
download(response.headers.location, dest).then(() => resolve());
} else {
reject(`Server responded with ${response.statusCode}: ${response.statusMessage}`);
}
});
request.on('error', err => {
reject(err.message);
});
});
}