I'm trying to update a Bootstrap progress bar according to the percent uploaded of a file.

I'm using the following code:

<!-- language: lang-js -->
xhr.upload.onprogress = function(e) {
  if (e.lengthComputable) {
    var percentComplete = (e.loaded / e.total) * 100;
    console.log(percentComplete + '% uploaded');
    $('.progress-bar').css('width', percentComplete+'%')
                      .attr('aria-valuenow', percentComplete);
  }
};
<!-- language: lang-html -->
<div class="progress progress-striped active">
  <div class="progress-bar" role="progressbar" id="progress-bar-file" style="width: 0.000001%"  
       aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>

However it does not work. The progress bar doesn't load, although the rest of the actions do happen, including the console logging, the file loading, and arriving to the database.

Any ideas?

The javascript to update the HTML seems correct. Here's a simple example which updates the progress bar using the code you provided:

Demo in StackSnippets

<!-- begin snippet: js hide: false --> <!-- language: lang-js -->
var eventStub = {total: 100, lengthComputable: true}

for (i = 0; i <= eventStub.total; i++) {
  setTimeout(function() {
    eventStub.loaded = i
    updateProgressBar(eventStub)
  },1000);
}

function updateProgressBar(e) {
  if (e.lengthComputable) {
    var percentComplete = (e.loaded / e.total) * 100;
    console.log(percentComplete + '% uploaded');
    $('.progress-bar').css('width', percentComplete+'%')
                      .attr('aria-valuenow', percentComplete);
  }
};
<!-- language: lang-html -->
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<link href="//seiyria.github.io/bootstrap-slider/stylesheets/bootstrap-slider.css" rel="stylesheet"/>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<script src="//seiyria.github.io/bootstrap-slider/javascripts/bootstrap-slider.js"></script>

<div class="progress progress-striped active">
  <div class="progress-bar" role="progressbar" id="progress-bar-file" style="width: 0.000001%"  
       aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- end snippet -->

One thing that could be affecting your request is if the XHR listeners is attached after you've already called open or send. Try setting up those listeners ahead of time.

Here's a Working Demo in Plunker

<sup>(you can't POST calls to stacksnippets.net because of the Access-Control-Allow-Origin).</sup>

<!-- language: lang-html -->
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>

<input type="file" id="fileInput" />
<input type="button" value="Upload" id="uploadBtn" />
<div class="progress progress-striped active">
  <div class="progress-bar" role="progressbar" id="progress-bar-file" style="width: 0.000001%"  
       aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- language: lang-js -->
$(function() {

  $('#uploadBtn').click(function() {
    var file = document.getElementById("fileInput").files[0];
    var xhr = new XMLHttpRequest();

    // attach listeners before posting
    xhr.upload.onprogress = updateProgressBar;
    
    xhr.open('POST', './test.php', true);
    xhr.send(file);

  });

  function updateProgressBar(e) {
    if (e.lengthComputable) {
      var percentComplete = (e.loaded / e.total) * 100;
      console.log(percentComplete + '% uploaded', e);
      $('.progress-bar').css('width', percentComplete + '%')
                        .attr('aria-valuenow', percentComplete);
    }
  }

})

Further Reading: