Tutorial :Progress/busy indicator while waiting for file download in javascript?



Question:

here is the situation: In the web application, user selects some options, submits form, and PDF file is dynamically generated on the server side and offered for download.

The problem: The generation of PDF file takes quite long (up to 1 minute). Some users think nothing is hapening and keep clicking the submit button again and again increasing server load and slowing it down even further.

I thougt about adding some busy indicator, which would show animated picture and message like "Please wait, your file is being generated", which seems very easy to do.

But: how to hide this indicator when the file is ready and "file download" dialog pops up? Otherwise, the message stays on screen even after the user has downloaded the file!

Seems very basic requirement, but I'm completely stuck. Thanks for any suggestions!


Solution:1

I've had to do this for something that took a lot longer (converting a video's format). It might seem like overkill to you but it did work.

  1. Move your PDF code out of process.
  2. When a job is started create a unique job ID and save it to session. Tell the PDF creator this ID.
  3. Make it write a status file (named as the job ID) to the server so that it writes "0% complete" and updates it every few seconds (this part depends on you being able to have a progress metric in your process... If it doesn't then this won't work)
  4. Use JS to pull that file down. You can display the progress to the user.
  5. When the progress equals "100% complete", push them to the PDF's location. It might help if you name this as the job ID too.*

*We had another download script that renamed it to a nice name (based on the original video filename) using the content-disposition header, but that's really up to you!

Edit: I should add that the waiting page was the result of clicking submit. It was a new pageload but there's no reason you couldn't AJAX the whole process, just make sure, as others have said, to disable the submit button on the first click to stop the user going ape on it.


Solution:2

I agree with the other respondents that your best bet would be to just disable the submit button on the form and give the user a busy indicator; however, for files that take a long time to generate it does make sense to have a more realistic indicator to the user that things didn't just hang.

One way that you might be able to implement a status bar, or an updating waiting message, is to have the client side JavaScript make an initial call to the server and have the server immediately respond back once it starts generation. Then you could have the client JavaScript poll the sever every n seconds to see if the file is complete. If you have a way of determining the file generation status then you could give a numeric response back for the progress bar percentage, or you could just reply back with a "still working" type of message.

I believe that this blog on asp.net discusses a similar setup.


Solution:3

I have a blog post with a potential solution to this problem:

http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx

This approach involves some cooperation between the client and server side code. It works like this (a full example including code can be found in my blog post linked above):

  • User clicks 'submit' button to generate file. Before the data is submitted to the server to be processed, client-side javascript does three things:
    1. Generates a "token" value and sets to a hidden field within the HTML form that is to be submitted. The value of the token isn't really important; just using the current date & time stamp down the second should suffice.
    2. Just after the token is set but still before allowing the form to be submitted, client side code puts up a "system busy" message to both let users know that something is happening and prevent them from submitting the form twice. The jQuery BlockUI plugin works great for this purpose.
    3. Finally, a time is configured to periodically poll for the presence of a cookie with a pre-defined name containing the token value created in step 1.
  • Now you have a nice "cover" on the client side that is letting the user know that something is happening and preventing them for clicking the button twice while the request can be processed on the server side. Just before sending the completed file back to the client as a download, set a cookie with the pre-defined name in the HTTP response that contains the token value that was submitted by the client.
  • When the HTTP response is received by the client, the timer code that is polling for the pre-defined cookie name containing the token value will find it and can then do the following:
    1. Unblock the UI
    2. Stop the timer/polling code.

I usually do this with a 1 second polling interval, so at most users have to wait 1 second between the time that the file download dialog is displayed in their browser and the time that the "system busy" message goes away.

That approach is, in my opinion, very quick and easy to implement. That said, given that your PDF generation takes about 1 minute, I think you're getting close to the point where taking that processing "out of band" and implementing something similar to what was explained in the accepted answer might be preferable.


Solution:4

You could asynchronously poll the server (using AJAX for example) to check if the generation of that particulair PDF has been completed. Depending on that result or a time-out re-enable that button and/or stop the animation.


Solution:5

I'd put this, or something like it, in an onSubmit event. The Busy block can just be a div with an ajax loading animation in the background. (I do suggest an animated gif, versus a Javascript animation.) Once the output is returned, the user will then see the PDF after their minute-long wait. You could even use a timer to decrement an estimate (60 seconds, say) and give the user some idea of how long it might take.

document.getElementById('busy').style.display = 'block';  document.getElementById('submit').disabled = 'disabled';  

The busy block:

<div id="busy">    <p>Your PDF is being generated, please wait.</p>  </div>  

And generic CSS...

#busy { display: none; background: url(/images/spinner.gif) no-repeat top left; padding-left: 24px; }  


Solution:6

Thanks everybody for the suggestions.

In the meantime, I tried one more approach:

a) In "onclick", disable the submit button and show busy indicator. b) On the server side, when file is generated, do not output it to the user, but save it to filesystem. Then, send the redirect to the same page, but with attribute "&downloadready=true" c) On page load, if "downloadready" attribute is true, initiate the file download.

It works, but has one downside: in IE, it shown warning "To protect your security, IE blocked the file download bla bla bla", which would be pretty annoying to users, I imagine.

So, let's try the AJAX polling approach then.


Solution:7

Not a complete answer to your question, but you could disable the submit button when the user made the first click.

That will take care of the "user keeps clicking thus slowing the server even further" problem.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »