I\'m creating an updater that downloads application files using the Node module request
. How can I use chunk.length
to estimate the remaining file
In case someone wants to know the progress without the use of other library but only request, then you can use the following method :
function downloadFile(file_url , targetPath){
// Save variable to know progress
var received_bytes = 0;
var total_bytes = 0;
var req = request({
method: 'GET',
uri: file_url
});
var out = fs.createWriteStream(targetPath);
req.pipe(out);
req.on('response', function ( data ) {
// Change the total bytes value to get progress later.
total_bytes = parseInt(data.headers['content-length' ]);
});
req.on('data', function(chunk) {
// Update the received bytes
received_bytes += chunk.length;
showProgress(received_bytes, total_bytes);
});
req.on('end', function() {
alert("File succesfully downloaded");
});
}
function showProgress(received,total){
var percentage = (received * 100) / total;
console.log(percentage + "% | " + received + " bytes out of " + total + " bytes.");
// 50% | 50000 bytes received out of 100000 bytes.
}
downloadFile("https://static.pexels.com/photos/36487/above-adventure-aerial-air.jpg","c:/path/to/local-image.jpg");
The received_bytes
variable saves the total of every sent chunk length and according to the total_bytes
, the progress is retrieven.
function download(url, callback, encoding){
var request = http.get(url, function(response) {
if (encoding){
response.setEncoding(encoding);
}
var len = parseInt(response.headers['content-length'], 10);
var body = "";
var cur = 0;
var obj = document.getElementById('js-progress');
var total = len / 1048576; //1048576 - bytes in 1Megabyte
response.on("data", function(chunk) {
body += chunk;
cur += chunk.length;
obj.innerHTML = "Downloading " + (100.0 * cur / len).toFixed(2) + "% " + (cur / 1048576).toFixed(2) + " mb\r" + ".<br/> Total size: " + total.toFixed(2) + " mb";
});
response.on("end", function() {
callback(body);
obj.innerHTML = "Downloading complete";
});
request.on("error", function(e){
console.log("Error: " + e.message);
});
});
};
This should get you the total you want:
req.on( 'response', function ( data ) {
console.log( data.headers[ 'content-length' ] );
} );
I get a content length of 9404541
If you are using "request" module and want to display downloading percentage without using any extra module, you can use the following code:
function getInstallerFile (installerfileURL) {
// Variable to save downloading progress
var received_bytes = 0;
var total_bytes = 0;
var outStream = fs.createWriteStream(INSTALLER_FILE);
request
.get(installerfileURL)
.on('error', function(err) {
console.log(err);
})
.on('response', function(data) {
total_bytes = parseInt(data.headers['content-length']);
})
.on('data', function(chunk) {
received_bytes += chunk.length;
showDownloadingProgress(received_bytes, total_bytes);
})
.pipe(outStream);
};
function showDownloadingProgress(received, total) {
var percentage = ((received * 100) / total).toFixed(2);
process.stdout.write((platform == 'win32') ? "\033[0G": "\r");
process.stdout.write(percentage + "% | " + received + " bytes downloaded out of " + total + " bytes.");
}
I wrote a module that just does what you want: status-bar.
var bar = statusBar.create ({ total: res.headers["content-length"] })
.on ("render", function (stats){
websockets.send (stats);
})
req.pipe (bar);
Using the cool node-request-progress module, you could do something like this in es2015:
import { createWriteStream } from 'fs'
import request from 'request'
import progress from 'request-progress'
progress(request('http://foo.com/bar.zip'))
.on('progress', state => {
console.log(state)
/*
{
percentage: 0.5, // Overall percentage (between 0 to 1)
speed: 554732, // The download speed in bytes/sec
size: {
total: 90044871, // The total payload size in bytes
transferred: 27610959 // The transferred payload size in bytes
},
time: {
elapsed: 36.235, // The total elapsed seconds since the start (3 decimals)
remaining: 81.403 // The remaining seconds to finish (3 decimals)
}
}
*/
})
.on('error', err => console.log(err))
.on('end', () => {})
.pipe(createWriteStream('bar.zip'))