Search code examples
phpjqueryajaxxmlhttprequestprogress

jquery ajax progress with custom calculation


I need advice on my ajax progress bar while executing a long PHP script treating pictures. I know there are plenty of questions on stackoverflow already like

Most of the examples I see are using the file size to calculate the progress. But in my case I would like to calculate percentage based on images_treated / total_images.

So I still can't make this work as I want.

In JS bellow I commented the not working progress function I took from another question and dataType: 'json' for tests but I would prefer if I can still use a JSON return.

Questions

  1. The console.log() will only log once - when the full script is done. Am I doing it wrong?
  2. What should I write to replace the comment?
  3. in some answers, the PHP headers are set to header('Content-Type: application/octet-stream'); is it mandatory or just nicer?

Javascript:

        $.ajax(
        {
            type: 'GET',
            // dataType: 'json',
            url: formAction,
            data: 'addImagesToArticle',
            cache: false,
            xhr: function()
            {
                var xhr = new window.XMLHttpRequest();

                // Download progress.
                xhr.addEventListener("progress", function(e)
                {
                    console.log(e);
                    // I saw this piece of code from another question it is supposed to work... Maybe my PHP?
                    /*var lines = e.currentTarget.response.split("\n");
                    var progress = lines.length ? lines[lines.length-1] : 0;

                    $('#progress').text(progress);*/
                }, false);
               return xhr;
            }
        });

My PHP is quite big so I just explain quickly: in the loop on pics I have variables $images_treated and $total_images. After the loop, a summary is returned to JS via JSON in an object like {error: bool, message: string, ...} so if there is a way to make the progress work without echoing but setting a JSON variable that would be perfect!

Thank you for your help!

[EDIT] to add context details.

I want to use this in an admin side, in an article edition with a WYSIWYG, I have dropzone taking care of my multiple images uploads.

then I see the preview of images while each image is put in temp folder on server. I can then remove some images if needed and once all images are definitive, i click a button that will process them for resizing 2 sizes and inject figure tags with img in the article WYSIWYG editor.


Solution

  • Waw I found a solution!

    I am happy to discover that new thing I did not know about PHP and share with people who also don't know (in step 3 bellow)!

    @riccardo was right talking about socket - which I don't know so well - but I did not need to go that far.

    So I had multiple things to solve in my case before being able to get closer of my goal.

    1. not using xhr.addEventListener("progress"... but a second ajax call in a timer: it will also be lighter-weight in resource consumption.

    2. rather than using a timer like setInterval or setTimeout - as requests are async it may come in unwanted order - use a recursive call in callback of first call like:

      function trackProgress()
      {
          $.getJSON('create-a-new-page.html', 'ajaxTrackProgress=1', function(response)
          {
              var progress = response.progress;
              $('#progress').text(progress);
      
              if (progress < 100) trackProgress();
          });
      }
      
    3. then realize that my second script call is delayed by first script still running? yes. So the key here is session_write_close()! I could dig in this way thanks to this good post: https://stackoverflow.com/a/1430921/2012407

    and I posted a very simple example here to reply to another question: https://stackoverflow.com/a/38334673/2012407

    Thank you for all your help in comments guys, it led me to this solution. ;)