Last active
September 26, 2023 19:04
-
-
Save motebaya/574a5bee8d300d6d71f22d7f67e04fd5 to your computer and use it in GitHub Desktop.
Asynchronous node js file downloader with progress bar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/node | |
const axios = require("axios"); | |
const progress = require("cli-progress"); | |
const fs = require("fs"); | |
const async = require("async"); | |
// https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string | |
const filesize = (a, b, c, d, e) => { | |
return ( | |
((b = Math), | |
(c = b.log), | |
(d = 1e3), | |
(e = (c(a) / c(d)) | 0), | |
a / b.pow(d, e)).toFixed(e ? 2 : 0) + | |
" " + | |
(e ? "kMGTPEZY"[--e] + "B" : "Bytes") | |
); | |
}; | |
/** | |
* https://github.com/axios/axios#request-config | |
* https://github.com/npkgz/cli-progress/tree/master#options-1 | |
*/ | |
const _download = async (url) => { | |
const prog = new progress.Bar({ | |
barCompleteChar: "━", | |
barInCompleteChar: "-", | |
fps: 10, | |
stream: process.stdout, | |
barsize: 30, | |
stopOnComplete: false, | |
clearOnComplete: false, | |
format: | |
"{filename}: {bar} {percentage}% | {current}/{totalMax} | ETA: {eta}s", | |
}); | |
const filename = url.split("/").slice(-1)[0]; | |
const stream = fs.createWriteStream(filename); | |
return new Promise(async (resolve, reject) => { | |
await axios({ | |
url: url, | |
method: "GET", | |
headers: { | |
"User-Agent": | |
"Mozilla/5.0 (Linux; Android 11; Infinix X6810) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Mobile Safari/537.36", | |
}, | |
responseType: "stream", | |
}).then((response) => { | |
let current = 1; | |
let total = parseInt(response.headers["content-length"]); | |
prog.start(total, 0); | |
prog.update({ filename: filename, totalMax: filesize(total) }); | |
response.data | |
.on("data", (chunk) => { | |
current += chunk.length; | |
prog.increment(chunk.length); | |
prog.update({ current: filesize(current) }); | |
}) | |
.pipe(stream); | |
response.data.on("error", (err) => { | |
prog.stop(); | |
reject(err); | |
}); | |
}); | |
stream.on("finish", () => { | |
prog.stop(); | |
resolve(`file saved as: ${filename}`); | |
}); | |
}); | |
}; | |
/** | |
* credit: @gist/motebaya | |
* 09-26-2023 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
here are 3 method for call it that i've research.
concurrency
, and maybe this likemax_workers
inThreadPoolExecutor
python?Demo:

concurrency
the progress bar are being overwritten.Demo:

.forEach
,'while
,for (...)
or .etc. but this method more than slow between 2 method before.Demo:

Using
Promise.all
when you need more fast download because this method run all task in concurrency, if you've to much url to download e.g:1000-2000
maybe will be consume more system resources. i didn't try it yet.Using:
async.queue
you can set by self how muchconcurrency
limit.