We help IT Professionals succeed at work.

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

Arthur Wang
Arthur Wang asked
on
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?
Comment
Watch Question

leakim971Multitechnician
Distinguished Expert 2019

Commented:
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

Author

Commented:
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

leakim971Multitechnician
Distinguished Expert 2019

Commented:
so did you check the header with the browser?

Author

Commented:
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.
leakim971Multitechnician
Distinguished Expert 2019

Commented:
Mac or Windows ?
leakim971Multitechnician
Distinguished Expert 2019

Commented:

Author

Commented:
thanks, but none of them works for me because the page is embedded inside another iframe. by the way, I use mac.
leakim971Multitechnician
Distinguished Expert 2019

Commented:
iframe is not an issue, you see all traffics...

Author

Commented:
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


Screen-Shot-2018-10-18-at-10.28.53-P.pngI 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.

Author

Commented:
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?
Multitechnician
Distinguished Expert 2019
Commented:
just did a simple test to  download a file and the cookie is well present

cookie present
package gp.leakim;

import java.io.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "DownloadServlet")
public class DownloadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;


    private static String strfilepath = "/Users/leakim/Desktop/test.txt";

    public DownloadServlet() {
        super();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("fileDownloadToken", "fileIsReady");
        response.addCookie(cookie);
        File fFile = new File(strfilepath);
        BufferedInputStream in = null;
        BufferedOutputStream sosStream = null ;
        try
        {
            response.setContentType( "application/octet-stream" );
            response.setHeader( "Content-Disposition", "attachment; filename=test.txt");
            in = new BufferedInputStream( new FileInputStream( fFile ) ) ;
            sosStream = new BufferedOutputStream( response.getOutputStream() ) ;

            byte[] buf = new byte[ 4 * 1024 ];  // 4K buffer
            int bytesRead;
            while( ( bytesRead = in.read( buf ) ) != -1 )
            {
                sosStream.write( buf, 0, bytesRead ) ;
            }
            sosStream.flush();
        }
        catch( IOException ex )
        {
            ex.printStackTrace() ;
        }
        finally
        {
            try { if( in != null) in.close(); } catch( IOException ex ) { }
            try { if( sosStream != null) sosStream.close(); } catch( IOException ex ) { }
        }
    }

}

Open in new window


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="DownloadIt">
    <button type="submit">SUBMIT</button>
  </form>
  </body>
</html>

Open in new window

Author

Commented:
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 ?
leakim971Multitechnician
Distinguished Expert 2019

Commented:
what you post does'nt look like struts...

Author

Commented:
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.