Link to home
Start Free TrialLog in
Avatar of Arthur Wang
Arthur WangFlag for United States of America

asked on

how to caputre the file downloading event and stop the spining icon.

I am trying to capture the event of the file downloading such that the spinning loader can be stopped, however, I tried multiple ways, it's still not working yet. please see my code below:

<script type="text/javascript">
$(document).ready(function(){
    $(":submit").click(function() {   	
        $('#loader').show();
    
/*
* above block of code works, below block does not
*    
        var fileDownloadCheckTimer;
        fileDownloadCheckTimer = window.setInterval(function(){
        var cookieValue = getCookie('fileDownloadToken');
        if(cookieValue == "fileIsReady") {
        	$('#loader').hide();
        	finishDownload();}
        },1000);
        
    });
});



/**
 * Get a cookie
 * @param {String} cname, cookie name
 * @return {String} String, cookie value 
 */
function getCookie(cname) {
    var name = cname + "="; //Create the cookie name variable with cookie name concatenate with = sign
    var cArr = window.document.cookie.split(';'); //Create cookie array by split the cookie by ';'
     
    //Loop through the cookies and return the cooki value if it find the cookie name
    for(var i=0; i<cArr.length; i++) {
        var c = cArr[i].trim();
        //If the name is the cookie string at position 0, we found the cookie and return the cookie value
        if (c.indexOf(name) == 0) {
        	document.getElementById("demo").innerHTML = c.substring(name.length, c.length);;
            return c.substring(name.length, c.length);
        }
    }
     
    //If we get to this point, that means the cookie wasn't find in the look, we return an empty string.
    return "";
}
 
 /**
  * Delete a cookie
  * @param {String} cname, cookie name
  */
 function deleteCookie(cname) {
     var d = new Date(); //Create an date object
     d.setTime(d.getTime() - (1000*60*60*24)); //Set the time to the past. 1000 milliseonds = 1 second
     var expires = "expires=" + d.toGMTString(); //Compose the expirartion date
     window.document.cookie = cname+"="+"; "+expires;//Set the cookie with name and the expiration date
  
 }

function finishDownload(){
	
	window.clearInterval(fileDownloadCheckTimer);
	deleteCookie('fileDownloadToken');
    hideConfirm();		
}

function hideConfirm() {
    var x = document.getElementById("loader");
    if (x.style.display == "block") {
        x.style.display = "none";
    } 
}

</script>

Open in new window


the servlet send out the cookie "fileIsReady" for the browser to capture:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		.........
		
		response.setContentType("application/octet");

		response.setHeader("Content-disposition", "attachment;filename=" + filename);

		Cookie cookie = new Cookie("fileDownloadToken", "fileIsReady");
		
		log.info("file download cookie is: " + cookie);
		response.addCookie(cookie);//for download signals
		
		ServletOutputStream sos = response.getOutputStream();
		workbook.write(sos);
		sos.flush();
		sos.close();
		workbook = null;
		log.debug("Finished to output excel stream.");

		
	}

Open in new window


My loader just keep running even though the file downloading has completed, which means the cookie---fileIsReady never been captured,  I carefully checked my source, nothing wrong, and the server does not report any error messages. can anybody help?
Avatar of leakim971
leakim971
Flag of Guadeloupe image

open a browser like chrome, do a right click on your page and click on Inspect
On the "Network" tab, check the different traffic, locate your file downloading, click on it, check the header, especially the response and check if you see you cookie
else post more of your code, a basic HTML part and the servlet java code
Avatar of Arthur Wang

ASKER

more detailed code blow:

html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title><bean:message key="system.name"/></title>

<!-- The block below is for bootstrap integration -->        
  	    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">	
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">        
        <link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css" >	 
		<script type="text/javascript" src="/kiosk_resources/javascript/jquery-2.1.4.min.js"></script>	
		<script type="text/javascript" src="/bootstrap/js/bootstrap.min.js"></script>	
<!-- above block is for bootstrap integration -->  

<script language="JavaScript" src="/kiosk_resources/javascript/calendar2.js"></script> 
<script type="text/javascript" language="JavaScript1.2" src="/kiosk_resources/javascript/date.js"></script>
<!-- above block is for calendar and date display -->


        <link rel="stylesheet" href="/kiosk_resources/javascript/jquery-ui.css">
        <script src="/kiosk_resources/javascript/jquery-ui.js"></script>  
  <script>
  $( function() {
    $( "#datepicker1, #datepicker2" ).datepicker();
  } );
  </script>

 
<style>
 select {
  height: 30px;
  padding: 5px 10px;
  cursor:pointer;
}
</style>  
 
<style>
.loader {
  border: 16px solid #f3f3f3;
  border-radius: 50%;
  border-top: 16px solid #3498db;
  width: 120px;
  height: 120px;
  -webkit-animation: spin 2s linear infinite; /* Safari */
  animation: spin 2s linear infinite;
    position:fixed;
    top: 60%;
    left: 60%;
    margin-top: -15em; /*set to a negative number 1/2 of your height*/
    margin-left: -15em; /*set to a negative number 1/2 of your width*/
    z-index: 1000;
}


/* Safari */
@-webkit-keyframes spin {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>

<script type="text/javascript">
$(document).ready(function(){
    $(":submit").click(function() {   	
        $('#loader').show();
        
        var fileDownloadCheckTimer;
        fileDownloadCheckTimer = window.setInterval(function(){
        var cookieValue = getCookie('fileDownloadToken');
        if(cookieValue == "fileIsReady") {
        	$('#loader').hide();
        	finishDownload();}
        },1000);
        
    });
});



/**
 * Get a cookie
 * @param {String} cname, cookie name
 * @return {String} String, cookie value 
 */
function getCookie(cname) {
    var name = cname + "="; //Create the cookie name variable with cookie name concatenate with = sign
    var cArr = window.document.cookie.split(';'); //Create cookie array by split the cookie by ';'
     
    //Loop through the cookies and return the cooki value if it find the cookie name
    for(var i=0; i<cArr.length; i++) {
        var c = cArr[i].trim();
        console.log(c);
        //If the name is the cookie string at position 0, we found the cookie and return the cookie value
        if (c.indexOf(name) == 0) {
        	document.getElementById("demo").innerHTML = c.substring(name.length, c.length);
        	console.log(c.substring(name.length, c.length));
            return c.substring(name.length, c.length);
        }
    }
     
    //If we get to this point, that means the cookie wasn't find in the look, we return an empty string.
    return "";
}
 
 /**
  * Delete a cookie
  * @param {String} cname, cookie name
  */
 function deleteCookie(cname) {
     var d = new Date(); //Create an date object
     d.setTime(d.getTime() - (1000*60*60*24)); //Set the time to the past. 1000 milliseonds = 1 second
     var expires = "expires=" + d.toGMTString(); //Compose the expirartion date
     window.document.cookie = cname+"="+"; "+expires;//Set the cookie with name and the expiration date
  
 }

function finishDownload(){
	
	window.clearInterval(fileDownloadCheckTimer);
	deleteCookie('fileDownloadToken');
    hideConfirm();		
}

function hideConfirm() {
    var x = document.getElementById("loader");
    if (x.style.display == "block") {
        x.style.display = "none";
    } 
}

</script>



</head>
<!-- above block is for jquery datepicker reference -->  

<body>


	<div class="container">
 	<div class="wrapper"> 
 	<div class="col-xs-12 col-md-10 col-md-offset-1 col-lg-10 col-lg-offset-1">






<form action="/.................../queryVisitReportByCustId.do" >

 <div class="form-group row"> 
		
	          <div class="col-xs-9" >
		
		        <br>
		        
				<div class="col-xs-6" >
				 <div class="input-group">
                  <span class="input-group-addon">
				     
				  </span>  
				  <input id="datepicker1" class="form-control" type="text" name="beginDate" placeholder="Begin Date example: 01/01/2018" value="">	
				  		
				</div>
				</div>
			

				<div class="col-xs-6" >
				 <div class="input-group">
                  <span class="input-group-addon">
				
				</span> 
				<input id="datepicker2" class="form-control" type="text" name="endDate" placeholder="End Date example: 01/01/2019" value="">				 
				</div>
				</div>
				
				<br>
				<br>
				<br>

				<button type = "submit" class ="btn btn-primary">Download Visit History</button>
         
              </div>
              
             </div>

 			
	</form>	
		
		
	</div>   
	</div>
	</div>	

   		
<!-- END CONTENT-->

</body>
</html>

Open in new window


servlet:

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.log4j.*;


public class OutputExcelServlet extends HttpServlet
{
	private static final long serialVersionUID = 6141531853383840414L;

	private final static Logger log = LogManager.getLogger(OutputExcelServlet.class);

	public OutputExcelServlet()
	{
		super();
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{

		log.debug("== excel filename:" + filename + ",workbook:" + workbook + ",beginDate:" + beginDate + ",endDate:" + endDate);

		response.setContentType("application/octet");

		response.setHeader("Content-disposition", "attachment;filename=" + filename);

		Cookie cookie = new Cookie("fileDownloadToken", "fileIsReady");
		
		log.info("file download cookie is: " + cookie);
		response.addCookie(cookie);   //for download signals
		
		ServletOutputStream sos = response.getOutputStream();
		workbook.write(sos);
		sos.flush();
		sos.close();
		workbook = null;
		log.debug("Finished to output excel stream.");

	
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		doGet(request, response);
	}

	public void init() throws ServletException
	{
	}
}

Open in new window

so did you check the header with the browser?
For some reason, this is a production site, and the previous engineer disabled the right click, and embedded the web page into an iframe for extra security. I probably have to setup a testing site, but that takes time to do it.
Mac or Windows ?
thanks, but none of them works for me because the page is embedded inside another iframe. by the way, I use mac.
iframe is not an issue, you see all traffics...
I am able to see the response header from inspector--> network:

Response headers (284 B)	
Connection	
Keep-Alive
Content-disposition	
attachment;filename=VisitHistoryByCustomerID.xls
Content-Type	
application/octet
Date	
Fri, 19 Oct 2018 05:14:24 GMT
Keep-Alive	
timeout=5, max=100
Server	
Apache/2.4.6 () mod_jk/1.2.43
Transfer-Encoding	
chunked

Open in new window


the console:

An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing

Open in new window


User generated imageI don't see the cookie which I sent from the servlet in the response header:

Cookie cookie = new Cookie("fileDownloadToken", "fileIsReady");
		
		log.info("file download cookie is: " + cookie);
		response.addCookie(cookie);//for download signals

Open in new window

though I am able to see it from the server log.
that's weird.
Since there is no way for me to capture the cookie at the browser, I am looking at the alternative solution, maybe try to capture the file name?

<script type="text/javascript">
$(document).ready(function(){
    $(":submit").click(function() {   	
        $('#loader').show();
        
        
        var request = new XMLHttpRequest();
        
        request.onload = function() {
          // Only handle status code 200
          if(request.status === 200) {
            // Try to find out the filename from the content disposition `filename` value
            var disposition = request.getResponseHeader('content-disposition');
            var matches = /"([^"]*)"/.exec(disposition);
            var filename = (matches != null && matches[1] ? matches[1] : 'VisitHistoryByCustomerID.xls');

            $('#loader').hide();
            hideConfirm();	
            }//if status 200
        };//onload function
    });//click function
});//ready function

function hideConfirm() {
    var x = document.getElementById("loader");
    if (x.style.display == "block") {
        x.style.display = "none";
    } 
}

Open in new window

the html code is:
<div id="loader" class="loader" style="display:none;"></div>  

Open in new window

however, the browser can not capture the event based on my testing, is my javascript code for the comparision correct?
ASKER CERTIFIED SOLUTION
Avatar of leakim971
leakim971
Flag of Guadeloupe image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
that's amazing, thanks for the testing code, which prove the cookies can be sent to the browser, however, for some reason my browser just can not see it, is it because I use struts ?
what you post does'nt look like struts...
Leakim971, maybe we can setup a time such that I could hire you as an expert to help me solve the problem? I am at the PST time zone.