Search code examples
node.jsspawn

Node.js Spawn Display STDOUT live not working


I have an app it receives file links and downloads them, for downloading I am used aria2c.

For doing this first I used exec, but since I want to get download progress then I used spawn

Here is code i am using for download file with aria2c:

'use strict';

const
    spawn = require( 'child_process' ).spawn,
    aria2c = spawn( 'aria2c', ['-x8', 'https://wa-us-ping.vultr.com/vultr.com.100MB.bin' ] );

aria2c.stdout.on( 'data', data => {
    console.log( `stdout: ${data}` );
});

aria2c.stderr.on( 'data', data => {
    console.log( `stderr: ${data}` );
});

aria2c.on( 'close', code => {
    console.log( `child process exited with code ${code}` );
});

When I run this code it doesn't print aria2c output to stdout, it only shows it when download finished.

I want to know how I can fix this.


Solution

  • I don't know aria2c very well, but this is what I came up with:

    // enable a specific log level
    aria2c = spawn( 'aria2c', ['--log-level=info', '-l-', '-x8', 'https://wa-us-ping.vultr.com/vultr.com.100MB.bin' ]);
    
    // find the percentage (this is not well-tested...)
    aria2c.stdout.on( 'data', data => {
      data = data.toString();
      if (/ETA:/.test(data)) {
        let pct = data.match(/\(.*?%\)/)[0];
        console.log( `stdout: ${ pct }` );
      }
    });
    

    (the rest of the code remains the same)

    The reason you can't (easily) capture the default output is because the progress lines are ended with just a carriage return, not a newline, which causes those lines to be buffered and you'll end up with one data event at the end that contains all those lines.

    By changing the loglevel, the progress lines are interspersed with other lines, which will either make the buffer fill up quicker, or cause more I/O flushes so the data event is triggered more often, allowing you to capture the progress data.