I have a page that allows the user to download a dynamically-generated file. It takes a long time to generate, so I\'d like to show a \"waiting\" indicator. The problem is,
Based on Elmer's example I've prepared my own solution. After elements click with defined download class it lets to show custom message on the screen. I've used focus trigger to hide the message.
JavaScript
$(function(){$('.download').click(function() { ShowDownloadMessage(); }); })
function ShowDownloadMessage()
{
$('#message-text').text('your report is creating, please wait...');
$('#message').show();
window.addEventListener('focus', HideDownloadMessage, false);
}
function HideDownloadMessage(){
window.removeEventListener('focus', HideDownloadMessage, false);
$('#message').hide();
}
HTML
<div id="message" style="display: none">
<div id="message-screen-mask" class="ui-widget-overlay ui-front"></div>
<div id="message-text" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-front ui-draggable ui-resizable waitmessage">please wait...</div>
</div>
Now you should implement any element to download:
<a class="download" href="file://www.ocelot.com.pl/prepare-report">Download report</a>
or
<input class="download" type="submit" value="Download" name="actionType">
After each download click you will see message your report is creating, please wait...
If you don't want to generate and store the file on the server, are you willing to store the status, e.g. file-in-progress, file-complete? Your "waiting" page could poll the server to know when the file generation is complete. You wouldn't know for sure that the browser started the download but you'd have some confidence.
old thread, i know...
but those, that are lead here by google might be interested in my solution. it is very simple, yet reliable. and it makes it possible to display real progress messages (and can be easily plugged in to existing processes):
the script that processes (my problem was: retrieving files via http and deliver them as zip) writes the status to the session.
the status is polled and displayed every second. thats all (ok, its not. you have to take care of a lot of details [eg concurrent downloads], but its a good place to start ;-)).
the downloadpage:
<a href="download.php?id=1" class="download">DOWNLOAD 1</a>
<a href="download.php?id=2" class="download">DOWNLOAD 2</a>
...
<div id="wait">
Please wait...
<div id="statusmessage"></div>
</div>
<script>
//this is jquery
$('a.download').each(function()
{
$(this).click(
function(){
$('#statusmessage').html('prepare loading...');
$('#wait').show();
setTimeout('getstatus()', 1000);
}
);
});
});
function getstatus(){
$.ajax({
url: "/getstatus.php",
type: "POST",
dataType: 'json',
success: function(data) {
$('#statusmessage').html(data.message);
if(data.status=="pending")
setTimeout('getstatus()', 1000);
else
$('#wait').hide();
}
});
}
</script>
getstatus.php
<?php
session_start();
echo json_encode($_SESSION['downloadstatus']);
?>
download.php
<?php
session_start();
$processing=true;
while($processing){
$_SESSION['downloadstatus']=array("status"=>"pending","message"=>"Processing".$someinfo);
session_write_close();
$processing=do_what_has_2Bdone();
session_start();
}
$_SESSION['downloadstatus']=array("status"=>"finished","message"=>"Done");
//and spit the generated file to the browser
?>
If you're streaming a file that you're generating dynamically, and also have a realtime server-to-client messaging library implemented, you can alert your client pretty easily.
The server-to-client messaging library I like and recommend is Socket.io (via Node.js). After your server script is done generating the file that is being streamed for download your last line in that script can emit a message to Socket.io which sends a notification to the client. On the client, Socket.io listens for incoming messages emitted from the server and allows you to act on them. The benefit of using this method over others is that you are able to detect a "true" finish event after the streaming is done.
For example, you could show your busy indicator after a download link is clicked, stream your file, emit a message to Socket.io from the server in the last line of your streaming script, listen on the client for a notification, receive the notification and update your UI by hiding the busy indicator.
I realize most people reading answers to this question might not have this type of a setup, but I've used this exact solution to great effect in my own projects and it works wonderfully.
Socket.io is incredibly easy to install and use. See more: http://socket.io/
When the user triggers the generation of the file, you could simply assign a unique ID to that "download", and send the user to a page which refreshes (or checks with AJAX) every few seconds. Once the file is finished, save it under that same unique ID and...
Then you can skip the whole iframe/waiting/browserwindow mess, yet have a really elegant solution.
If Xmlhttprequest with blob is not an option then you can open your file in new window and check if eny elements get populated in that window body with interval.
var form = document.getElementById("frmDownlaod");
form.setAttribute("action","downoad/url");
form.setAttribute("target","downlaod");
var exportwindow = window.open("", "downlaod", "width=800,height=600,resizable=yes");
form.submit();
var responseInterval = setInterval(function(){
var winBody = exportwindow.document.body
if(winBody.hasChildNodes()) // or 'downoad/url' === exportwindow.document.location.href
{
clearInterval(responseInterval);
// do your work
// if there is error page configured your application for failed requests, check for those dom elemets
}
}, 1000)
//Better if you specify maximun no of intervals