Download Progress Bar with Axios

OpenJavaScript 0

Last updated: December 15, 2022.

You can track the download progress of a HTTP request using Axios.

To do so, define an options object for the request, which is passed into the request call as a second argument.

On this object, include an onDownloadProgress property whose value is a function. This function will fire every time there is progress on the download.

Information on download progress is available as an object that is automatically passed into the function by Axios every time it fires:

const options = {
// Defines options for request

  responseType: 'blob',
  // For a file (e.g. image, audio), response should be read to Blob (default to JS object from JSON)

  onDownloadProgress: function(progressEvent) {
  // Function fires when there is download progress

      console.log(Math.floor(progressEvent.loaded / progressEvent.total));
      // Logs percentage complete to the console

  }

}

axios.get('https://picsum.photos/1000/1000', options)
// Request with options as second parameter
  .then(res => console.log(res))
  .catch(err => console.log(err))

To visualize download progress with a bar, it would be possible to use the native <progress> HTML element. But its implementation varies across browsers.

Therefore, in the code example below, a CSS progress bar is updated of download progress information coming from Axios.

To do this, the progress-bar-fill element is embedded within progress-bar with a starting width of 0%. As the download progresses, the onDownloadProgress function updates its width until the download is complete.

Additionally, download progress is printed as a text value inside the progress-text element:

<style>

  body {
    font-family: Arial, Helvetica, sans-serif;
  }

  /* CSS Progress bar */
  .wrapper {
      width: 600px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      margin: 0px auto;
      margin-top: 30vh;
  }
  .progress-bar {
      width: 100%;
      background-color: whitesmoke;
      padding: 2px;
  }
  .progress-bar-fill {
      display: block;
      height: 40px;
      background-color: #65ef88;
      border-radius: 3px;
      width: 0%; /* Starts at 0%, updates with download progress */
          
      transition: width 30ms ease-in-out;
  }
  .progress-text {
      font-size: 1.5rem;
      padding: 10px;
  }
  img {
      display: block;
      margin: 0px auto;
  }
  
</style>
<body>

  <div class="wrapper">
    <div class="progress-bar">
      <span class="progress-bar-fill"></span>  
    </div>
    <span class="progress-text">Download starting...</span>
  </div>

</body>
<script>
    
  const fill = document.querySelector('.progress-bar-fill');
  const text = document.querySelector('.progress-text');
  const wrapper = document.querySelector('.wrapper');

  const options = {

    responseType: 'blob',

    onDownloadProgress: function(progressEvent) {
        const percentComplete = Math.floor((progressEvent.loaded / progressEvent.total)*100);
        fill.style.width = percentComplete+"%";
        text.textContent = percentComplete+"%";
    }

  }

  axios.get('https://picsum.photos/400/400', options)
    .then(res => {
      // Do something with the result here
      console.log(res); 
    })
    .catch(err => console.log(err))

</script>

Related links