How To Hide An Animated Gif After The File Has Been Downloaded ?
Solution 1:
Both your questions (this and the other one) are examples of the XY problem.
Before looking for specific technologies, techniques or hacks, start defining clearly your goal:
The Goal
- Download a file without moving to other pages;
- Meanwhile, showing an indicator (progress bar, animated gif, overlay, etc...);
- When the file has been downloaded, hide the indicator.
The Solution
Bound your trigger to a javascript function as described here:
<ahref="javascript:myJsFunction();"> download </a>
In your Javascript function: show the indicator, start a timer to check if the download is over (and then hide the indicator), and download the file:
functionmyJsFunction(){
$("#containerWithGifImage").fadeIn("fast"); // Show the indicatorsetInterval(function(){
$.ajax({
url : "/isDownloadFinished.action", type : "GET",
success : function(data,textStatus,jqXHR) {
$("#containerWithGifImage").fadeOut("fast"); // Hide the indicator
},error : function(jqXHR, textStatus, errorThrown) {
console.log("Download is still in progress, do nothing...");
}
});
}, 1000); // Check every second if download has finishedwindow.location='/download.action'; // Start the download
}
Download.action must put in the session an attribute indicating the download has started, updating it when it's over.
Since with the stream
result you're consigning the control of the response to the browser (and hence you can't run code when it has finished), you can write directly to the response and then return NONE
, as described here:
publicclassDownloadextendsActionSupportimplementsSessionAware, ServletResponseAware {
@SetterprivateMap session;
@SetterprivateHttpServletResponse response;
publicStringexecute(){
ServletOutputStream os = null;
try {
session.put("DOWNLOAD_STATUS","active");
response.setContentType("myContentType");
response.addHeader("Content-Disposition", "attachment; filename=\"foo.bar\"");
os = response.getOutputStream();
IOUtils.copy(getMyFileInputStreamSomeHow(), os);
} finally {
IOUtils.closeQuietly(os);
session.put("DOWNLOAD_STATUS","finished");
}
returnNONE;
}
}
You can also have the browser drawing a progressbar for you by specifying the Content-Length
response header (response.setHeader("Content-Length", 1337);
) as described here, where you can also see a similar mechanism to prevent concurrent downloads.
In the IsDownloadFinished.action, you need to check the session attribute. I it doesn't exist or is different from finished, it means the download is not started yet, or still in progress, hence do nothing. Otherwise, return a succesfull httpheader that will make your jQuery $.ajax function to run the success:
callback. You can use either httpHeader
or json
, as described here:
@Results({
@Result(name = ActionSupport.SUCCESS, type="httpheader", params = {"status", "200"}),
@Result(name = ActionSupport.ERROR, type="httpheader", params = {"error", "500"})
})
public class IsDownloadFinished extends ActionSupport implements SessionAware {
@Setter private Map session;
publicStringexecute(){
if ("finished".equals(session.get("DOWNLOAD_STATUS")) {
session.remove("DW_STATUS");
returnSUCCESS;
}
returnERROR;
}
}
There are different solutions to this problem, I've shown you the simplest one. More elegant and complex solutions would involve long-held requests and Comet techniques (read: WebSocket), but I suppose you can start with the polling-timer from this kick-off example, customizing it for your needs, and eventually evolving it when more comfortable with the argument.
Post a Comment for "How To Hide An Animated Gif After The File Has Been Downloaded ?"