Search code examples
javascriptajaxxmlhttprequest

How to set progress bar from 0 to 100% for each uploaded image separately


I want to upload multiple images but in separate XMLHttpRequest.

The requests should executes itself sequentially (one by one) and not simultaneously.

That's because I want the progress bar to go from 0 to 100% for each uploaded image.

Using this code seems requests executes simultaneously because:

  • progress bar is flickering - constantly goes back and forward
  • all finito in console appears at the same time, i.e. at the end of entire process

If I write ajax.open("POST", "a_pro_up.php, false") instead of ajax.open("POST", "a_pro_up.php");:

  • finitos in console appears sequentially
  • but progress bar doesn't work at all

How to get fluently rising progress bar for each uploaded image separately ?

<input type="file" class='inpfi' id='inpimg' multiple accept="image/jpeg">
<progress class='pbar' id='pbar' value='0' max='100'> 0% </progress>

   inpimg.on('change', function(){
        var files = inpimg[0].files;
        for(var i = 0; i < files.length; i++){
            var file = files[i];
            var fd = new FormData();
            fd.append('id', urw);
            fd.append('upimg', file);
            var ajax = new XMLHttpRequest();
            ajax.upload.addEventListener("progress", up_progress, false);
            ajax.addEventListener("load", up_img_finito, false);
            ajax.open("POST", "a_pro_up.php");
            ajax.send(fd);
        }
    });  

function up_progress(e){
    let percent = (e.loaded / e.total) * 100;
    pbar.val(Math.round(percent));
}

function up_img_finito(){
    console.log('finito');
}

Solution

  • I recommend to never loop ajax.

    Here is a version that runs sequentially as you want

    let files, cnt = 0,
      max = 0;
    
    const up_img_finito = () => {
      console.log('finito', cnt);
      cnt++
      upload();
    }
    const up_progress => (e) {
      let percent = (e.loaded / e.total) * 100;
      pbar.val(Math.round(percent));
    };
    
    const upload = () => {
      if (cnt >= max) {
        up_img_finito()
        return;
      }
      let file = files[i];
      let fd = new FormData();
      fd.append('id', urw);
      fd.append('upimg', file);
      let ajax = new XMLHttpRequest();
      ajax.upload.addEventListener("progress", up_progress, false);
      ajax.addEventListener("load", up_img_finito, false);
      ajax.open("POST", "a_pro_up.php");
      ajax.send(fd);
    };
    document.getElementById('inpimg').addEventListener('change', () => {
      files = inpimg[0].files;
      max = files.length;
      upload()
    });