0

Currently, I have a lot of linux based clients downloading firmware updates from my webserver.

After the client has successfully downloaded the firmware file, my server needs to execute a few scripts, which logs in to the client and performs some tasks.

Is there a way for a node server to keep track of the clients download progress, so I can execute the needed scripts once the file has been downloaded?

Drejer
  • 135
  • 1
  • 13
  • Some code snippets would be great! How do they download the files? What does your controller look like? Without any code nobody could answer this question properly. – coderocket Mar 02 '17 at 09:13
  • The client downlods the firmware file through HTTP. I don't see why code snippets would be nessecary. I'm simply asking if there is a way for a node server to see active client requests that are still being sent, and possibly the progress of the download. – Drejer Mar 02 '17 at 09:35
  • @Drejer there's a difference between executing some code at the end of a download, seeing the progress of a download, and seeing all active downloads. The first may be implemented easily, but it depends on how exactly you are serving the files (static middleware, `res.sendFile()`, `res.download()`, ...). Hence, "code snippets". – robertklep Mar 03 '17 at 07:09

4 Answers4

0

Ok so I will try.

If you serve your Firmware as static files through Apache/Nginx and direct url call. You don't get the progress inside your NodeJS script.

If you serve your files via stream inside a express controller you can listen to the progress. Look at this answer here https://stackoverflow.com/a/42273080/3168392

Community
  • 1
  • 1
coderocket
  • 584
  • 3
  • 11
0

You will have to use a socket connection to make sure the node server gets update from the client of the progress of the file being downloaded. Something like this

CLIENT_CODE

var socket = io('http://localhost');
socket.on('connect', function(){});
socket.on('data_reciving', parts.pop(),function(percentage){
  if(parse_data(percentage) === 100){
       client.socket.emit('downloadCompleted', {fileName:'test'});
   }else{
      //do nothing
   }
});

SERVER_CODE:

sockets.on('connection', function (socket) {
  //listen to the event from client 
  socket.on('downloadCompleted', function (data) {
     connect_to_client();
     do_some_operation();

     socket.emit('ALLDONE',{some_data});
  });
});

I guess this helps ,you can use this post for reference.

Community
  • 1
  • 1
damitj07
  • 2,689
  • 1
  • 21
  • 40
  • Thanks for the suggestion. The clients are using curl to download the file, unfortunately I can't change this. I guess I was hoping for some Express middleware that could throw some event, once a file is fully downloaded using from the server using HTTP. – Drejer Mar 02 '17 at 10:30
  • You will have to use some sort of connection lib to throw or publish events from the server.... or maybe have a polling to check with server – damitj07 Mar 02 '17 at 10:55
0

I found some code that seems to fit my needs. With the code below, I can detect both the progress of a user's download from the server-side, and fire an event once the file transfer completes.

var http = require("http");
var fs = require("fs");
var filename = "./large-file";

var serv = http.createServer(function (req, res) {

  var sent = 0;
  var lastChunkSize = 0;

  var stat = fs.statSync(filename);
  res.setHeader('Content-disposition', 'attachment; filename=large-file.iso');
  res.setHeader('Accept-Ranges', 'bytes');
  res.setHeader('Keep-Alive', 'timeout=5, max=100');
  res.writeHeader(200, {"Content-Length": stat.size});
  var fReadStream = fs.createReadStream(filename, { highWaterMark: 128 * 1024 });
  fReadStream.on('data', function (chunk) {
    if(!res.write(chunk)){
      fReadStream.pause();
      lastChunkSize = chunk.length;
      console.log('Sent', sent, 'of', stat.size);
    }
 });
 fReadStream.on('end', function () {
   console.log('Transfer complete.');
   res.end();
 });

 res.on("drain", function () {
   sent += lastChunkSize;
   fReadStream.resume();
 });
});

serv.listen(3001);
Drejer
  • 135
  • 1
  • 13
0

If you just want to run some code when a download has finished, you can use on-finished:

const onFinished = require('on-finished');

app.use((req, res, next) => {
  onFinished(res, (err, res) => {
    ...log some data, perform some housekeeping, etc...
  });
  next();
});

As is, it will attach a "finished" listener to all responses, which is probably not what you want. Since this is plain Express middleware, you can attach it to specific routes instead (but how depends on how exactly the files are being served).

robertklep
  • 198,204
  • 35
  • 394
  • 381