How to display a progress status/spinner when outp

2019-05-03 12:53发布

问题:

I have a webform with a Download LinkButton, on the button's click event I'm fetching data and then generating an .XLSX file for download. During the generation of the file, Response.Clear() is called, Response.ContentType is set and eventually Response.End() is called.

I need to display a spinner .gif during that operation. Once the file has been generated and the file "Open/Save" dialog pops up, the spinner should not display. Unfortunately, since I'm changing the content type and calling Response.End there is no response returned back to the page to work with.

Can anyone please provide a little help with this scenario?

回答1:

I actually ended up going with a solution that did not require the use of an iFrame. Instead I make use of a Cookie, which the file generation process writes into it simple a Name Value pair. This cookie can then be checked later from the client side via JavaScript to determine when the response (.xlsx file) has completed.

The result should be that the loading spinner image should display until the .xls file has been generated and returned to the client (Cookie contains the DownloadComplete=true Name Value pair).

  1. In the OnClientClick event for the LinkButton:

    function startFileDownload(){
    
    // Set Timout for calling checkState function again
    setTimeout(checkState, 1100);
    setCookie('DownloadComplete', '', 1);
    
    // Download is starting, Hide Download LinkButton
    document.getElementById('<%= btnDownloadExcel.ClientID%>').style.display = "none";
    
    // Display progress spinner
    var img = document.getElementById("image1");
    img.src = "Images/99.GIF";
    document.getElementById('image1').className = "spinnerDisplay";
    }
    
  2. Here is the JavaScript code for the checkState function:

    function checkState()
    {
        var img = document.getElementById("image1");
        var finished = getCookie("DownloadComplete");
        // Check to see if download is complete 
    if (!isEmpty(finished)) {
        setCookie('DownloadComplete', '');
        // Download is complete, Hide progress spinner
        img.className = "spinnerHide";
        document.getElementById('<%= btnDownloadExcel.ClientID%>').style.display = "";
    } else {
        // Refresh progress spinner, Set Timout for calling checkState function again
        img.src = "Images/99.GIF";
        setTimeout(checkState, 1100);
    }
    }
    
  3. Here is the JavaScript code for the setCookie and the getCookie functions:

    function setCookie(cName, value){
    var now = new Date();
    var time = now.getTime();
    time += 3600 * 1000;
    now.setTime(time);
    document.cookie = cName + "=" + value 
    + '; expires=' + now.toGMTString() + '; path=/';        
    }
    
    function getCookie(cName)
    {
        var i, x, y, ARRcookies = document.cookie.split(";");
        for (i = 0; i < ARRcookies.length; i++) {
        x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
        y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
        x = x.replace(/^\s+|\s+$/g, "");
    
        if (x == cName) {
            return unescape(y);
        }
        }
    }
    
  4. Then on the server side in the class that generates the .xlsx file, after clearing the HTTP Response add a Name Value pair to the Cookie:

     HttpContext.Current.Response.Clear();
    
     // Append a cookie that will tell the browser the file has finished processing 
     // and is included in that stream (note specific path must match same path for cookie set in JavaScript)            
     HttpCookie cookie = new HttpCookie("DownloadComplete", "true");
     cookie.Expires = DateTime.Now.AddMinutes(60);
     cookie.Path = "/";
     HttpContext.Current.Response.AppendCookie(cookie);
     //Other code here to specify the MIME type, setup the HTTP header 
     //and Response.BinaryWrite out the file
     HttpContext.Current.Response.End();
    


回答2:

It should go like this : (one solution among others)

1) create an iframe on your page which will actually download your file ( so your main page wont be blank )

2) Add a cookie to the response. via

Response.AddHeader("content-disposition", "attachment;filename=1.jpg");

3) when a user press "download" you set (via js) the src for the iframe to download the file. and you show the spinner. after this , you start reading via setInterval , if theres a cookie. if thereis - the download has finished so you can hide the spinner.