Detect when browser receives file download

前端 未结 22 1734
陌清茗
陌清茗 2020-11-21 04:55

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,

22条回答
  •  死守一世寂寞
    2020-11-21 05:43

    This Java/Spring example detects the end of a Download, at which point it hides the "Loading..." indicator.

    Approach: On the JS side, set a Cookie with a Max Expiration Age of 2 min, and poll every second for cookie expiration. Then the server-side overrides this cookie with an earlier expiration age -- the completion of the server process. As soon as the cookie expiration is detected in the JS polling, "Loading..." is hidden.

    JS Side

    function buttonClick() { // Suppose this is the handler for the button that starts
        $("#loadingProgressOverlay").show();  // show loading animation
        startDownloadChecker("loadingProgressOverlay", 120);
        // Here you launch the download URL...
        window.location.href = "myapp.com/myapp/download";
    }
    
    // This JS function detects the end of a download.
    // It does timed polling for a non-expired Cookie, initially set on the 
    // client-side with a default max age of 2 min., 
    // but then overridden on the server-side with an *earlier* expiration age 
    // (the completion of the server operation) and sent in the response. 
    // Either the JS timer detects the expired cookie earlier than 2 min. 
    // (coming from the server), or the initial JS-created cookie expires after 2 min. 
    function startDownloadChecker(imageId, timeout) {
    
        var cookieName = "ServerProcessCompleteChecker";  // Name of the cookie which is set and later overridden on the server
        var downloadTimer = 0;  // reference to timer object    
    
        // The cookie is initially set on the client-side with a specified default timeout age (2 min. in our application)
        // It will be overridden on the server side with a new (earlier) expiration age (the completion of the server operation), 
        // or auto-expire after 2 min.
        setCookie(cookieName, 0, timeout);
    
        // set timer to check for cookie every second
        downloadTimer = window.setInterval(function () {
    
            var cookie = getCookie(cookieName);
    
            // If cookie expired (NOTE: this is equivalent to cookie "doesn't exist"), then clear "Loading..." and stop polling
            if ((typeof cookie === 'undefined')) {
                $("#" + imageId).hide();
                window.clearInterval(downloadTimer);
            }
    
        }, 1000); // Every second
    }
    
    // These are helper JS functions for setting and retrieving a Cookie
    function setCookie(name, value, expiresInSeconds) {
        var exdate = new Date();
        exdate.setTime(exdate.getTime() + expiresInSeconds * 1000);
        var c_value = escape(value) + ((expiresInSeconds == null) ? "" : "; expires=" + exdate.toUTCString());
        document.cookie = name + "=" + c_value + '; path=/';
    }
    
    function getCookie(name) {
        var parts = document.cookie.split(name + "=");
        if (parts.length == 2 ) {
            return parts.pop().split(";").shift();
        }
    }
    

    Java/Spring Server Side

        @RequestMapping("/download")
        public String download(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //... Some logic for downloading, returning a result ...
    
            // Create a Cookie that will override the JS-created Max-Age-2min Cookie 
            // with an earlier expiration (same name)
            Cookie myCookie = new Cookie("ServerProcessCompleteChecker", "-1");
            myCookie.setMaxAge(0); // this is immediate expiration, 
                                   // but can also add +3 sec. for any flushing concerns
            myCookie.setPath("/");
            response.addCookie(myCookie);
            //... -- presumably the download is writing to the Output Stream...
            return null;
    }
    

提交回复
热议问题