1

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.

Community
  • 1
  • 1
antoni
  • 5,001
  • 1
  • 35
  • 44
  • An AJAX request and the work done on the server to serve that request is a treated single entity. This means that you cannot know what work the server is doing simply from the `progress` event, only how much data has been sent/received. If you want to know the progress in the steps the server has taken you would need to code the server so that it stores it's last completed task on an endpoint which is reachable from a second AJAX request which you then call at intervals while the main request is running. – Rory McCrossan Jul 09 '16 at 17:44
  • Yes if I understand you I need a second php to send progress, so the progress can be stored in session if needed its fine. But then how do I question both PHP scripts from one AJAX in JS file? – antoni Jul 09 '16 at 17:48
  • I think that what you are trying to achieve is slightly different from your approach. Here you can find a [question](http://stackoverflow.com/a/18964123/6565883) about this topic. You can print from the server side the status of the processing. Hope it helps. – Riccardo Jul 09 '16 at 17:48
  • @antoni you can't do it in a single AJAX request, you need to use at least 2. That's why this method is considered *very* outdated (note the guide linked above is from over 5 years ago) and it will put quite a lot of extra load on your server as you're exponentially increasing the number of requests made to the server if you follow this pattern – Rory McCrossan Jul 09 '16 at 17:51
  • @riccardo, Oh I see... thanks it helps a bit. So I should have a XHR open, then do a timeout and check what is given from PHP every x milliseconds. correct? but if I can get a bit more help to write it it would be perfect! – antoni Jul 09 '16 at 17:54
  • Is requirement to `echo` to requesting page the status of `images_treated / total_images`? – guest271314 Jul 09 '16 at 17:54
  • @RoryMcCrossan, so if it looks outdated method do you recommend another way at all? – antoni Jul 09 '16 at 17:55
  • @antoni, as Rory pointed out this approach is very old and it breaks the performaces. You should be careful using it, you should try and change completely the approach. – Riccardo Jul 09 '16 at 17:56
  • @guest271314, yes I need to see what picture is being treated, so at least a counter or percentage. – antoni Jul 09 '16 at 17:56
  • Hmmm, i feel outdated lol. 1- it is for admin side. 2- please submit me a nice answer offering alternatives so I will like it for sure! and so will next readers! – antoni Jul 09 '16 at 17:58
  • @antoni, [this](http://stackoverflow.com/a/27077225/6565883) could be an approach where you can start with. It is for an upload script, but the logic can be adapted for your goals. A push from the server instead of a fetch from the client. – Riccardo Jul 09 '16 at 18:00
  • If you absolutely need to know which file is being treated by the request, then no, there's no alternative. But I would strongly suggest you change the requirements if that was the case. – Rory McCrossan Jul 09 '16 at 18:00
  • I really wonder why it seems outdated though, can't find another nicer way than an AJAX progress rather than nothing? – antoni Jul 09 '16 at 18:00
  • You could possibly modify this approach http://stackoverflow.com/questions/38172978/progress-bar-for-multiple-ajax-requests-with-stages-of-completion-is-it-possibl/ – guest271314 Jul 09 '16 at 18:02
  • @Riccardo, this is where i get my idea and starting from. So good idea or outdated? :) – antoni Jul 09 '16 at 18:03
  • @antoni, I don't think pushing is outdated. The approach that I can think now is to use websockets. You start the connection with the server, send a message to start the processing and get responses about the status (this is the normal 'realtime' approach and it doesn't break performance because everything is done with just one connection). – Riccardo Jul 09 '16 at 18:05
  • hmm Im overwhelmed with more readings now haha but not sure what I can improve in the concept. it is simple, I just want to click a proceed button and have a nice progressbar telling me which picture is being processed, I remember Wordpress, Joomla and eZ Publish doing it! – antoni Jul 09 '16 at 18:07
  • 1
    @antoni, don't trust CMSs, they do very bad things just to have glittery UIs and mislead developers. – Riccardo Jul 09 '16 at 18:08
  • hahaha. Please someone guide me with a tutorial, im lost now. really I didn't expect that would be a difficult task :p – antoni Jul 09 '16 at 18:10
  • @antoni, simple as can be try [this](http://www.phpbuilder.com/articles/application-architecture/optimization/creating-real-time-applications-with-php-and-websockets.html). I have not tried it but it seems to achieve the goal. – Riccardo Jul 09 '16 at 18:12
  • Another approach could be to create a `` element for each uploaded file, see http://stackoverflow.com/questions/28856729/upload-multiple-image-using-ajax-php-and-jquery/ – guest271314 Jul 09 '16 at 18:12
  • @guest271314, the picture upload is done at another time before, for this case images are already on server in temp dir and then they are resized with image magik Riccardo, it's gonna take me a day, i will try tmr if no better way :/ Thank you guys for your concerns already. – antoni Jul 09 '16 at 18:17
  • @antoni _"the picture upload is done at another time before, for this case images are already on server in temp dir and then they are resized with image magik"_ Are you trying to request re-sized images from server, use `` to display which image is currently being processed by `XMLHttpRequest` from total images sent to `document` at response from server? – guest271314 Jul 09 '16 at 18:20
  • @guest271314, no forget the upload part, i just click on a button that triggers server images resizing. – antoni Jul 09 '16 at 18:23
  • @antoni _"i just click on a button that triggers server images resizing"_ Yes, what is expected result? Processing of re-size at server, or image being received? – guest271314 Jul 09 '16 at 18:23
  • let me update the question to set the context – antoni Jul 09 '16 at 18:25

1 Answers1

1

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. ;)

Community
  • 1
  • 1
antoni
  • 5,001
  • 1
  • 35
  • 44