Axios — Download Progress in Node.js

Axios provides a clean promise-based API to interact with HTTP endpoints. It supports a variety of formats and use-cases. A previous tutorial showed you how to download files with Axios in Node.js.

This tutorial walks you through the process of adding a progress bar when downloading files with Axios in Node.js.

Download Progress with Axios in Node.js

Axios Series Overview

Preparation

This tutorial uses a third-party package to display a progress bar on the terminal. You can find more details about the visionmedia/progress package in the linked GitHub repository.

You may install the progress package from NPM:

npm i progress  

Show a Progress Bar When Downloading Files with Axios

When downloading files from the Internet, you should reach for a streaming download. Streams are great to handle large files by chunking them into small pieces and downloading the files as individual chunks.

Using a stream works nice with a progress bar. Typically, when sending a download request to the remote server, it responds with the total size of the file. This total file size is stored in the content-length response header.

Some servers don’t set the content-length header accordingly. They may use a different response header instead. If you can’t pick the file size from content-length, explore the headers and try to find the file size.

Show a Progress Bar for Axios Downloads

This tutorial downloads an image from Unsplash to your local disk. The sample code sends a request to Unsplash using Axios and expects a stream response. As soon as the response is available, you should grab the content-length value from the response headers.

Initialize the progress bar using the total file size and then pipe the response stream to the file destination on your file system.

While streaming the response to disk, you may listen for the data events on the file stream coming from Axios. The stream sending the unsplash image to your machine emits the data event every time it provides the next chunk. You can then notify the progress bar to update the status.

Here’s a working implementation of an Axios download showing its progress on the terminal:

'use strict'

const Fs = require('fs')  
const Path = require('path')  
const Axios = require('axios')  
const ProgressBar = require('progress')

async function downloadImage () {  
  const url = 'https://unsplash.com/photos/AaEQmoufHLk/download?force=true'

  console.log('Connecting …')
  const { data, headers } = await Axios({
    url,
    method: 'GET',
    responseType: 'stream'
  })
  const totalLength = headers['content-length']

  console.log('Starting download')
  const progressBar = new ProgressBar('-> downloading [:bar] :percent :etas', {
      width: 40,
      complete: '=',
      incomplete: ' ',
      renderThrottle: 1,
      total: parseInt(totalLength)
    })

  const writer = Fs.createWriteStream(
    Path.resolve(__dirname, 'images', 'code.jpg')
  )

  data.on('data', (chunk) => progressBar.tick(chunk.length))
  data.pipe(writer)
}

downloadImage()  

That’s it! Determine the response size, use response streaming and listen for data events on the response stream to update your progress bar accordingly.

Why Not Use the onDownloadProgress Event From Axios?

Axios has a built-in onDownloadProgress event. This event is only available in the browser. When using Axios in Node.js you must implement the progress handling yourself.


Mentioned Resources

Explore the Library

Find interesting tutorials and solutions for your problems.