views:

1695

answers:

6

Hi all,

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!

A: 

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.

Thomas Stock
+1  A: 

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.

Kevin
This would slow generation of the PDF, you have to store its status/progress somewhere for AJAX to get it. AJAX polling isn't the end-all fix.
The Wicked Flea
I know what's required in order to develop this solution. You can poll at a 5 - 10 second interval for example, it doesn't have to be near realtime. It all depends on what you want the user experience to be. But a different solution is hard to come by in this case or are you convinced otherwise?
Kevin
And indeed AJAX / polling isn't the end-all fix.
Kevin
A: 

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; }
The Wicked Flea
+1  A: 

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.

Rob
+2  A: 

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.

Oli
A: 

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.

audras
Or the second load could just display the link to the file if the browser is IE-based; that isn't hard to detect.
The Wicked Flea