瀏覽器監聽文件下載實現


之前在做類似下載功能的時候,很少會考慮那些優化問題。直接一個超鏈接了事。

然后。。。我遇到了兩個坑。

坑1,A項目中的導出按鈕,測試妹紙在火狐瀏覽器上死活點不出來,而我自己的火狐上是正常的,最后我發現,是迅雷下載插件惹的禍T。T 

坑2,B項目中,某運營連續點了10次導出按鈕,然后。。。網站變得很卡。

 

對於坑1,我們可以用iframe去實現下載。

$('#J-download').on('click',function(){
  var iframe=$('<iframe />').attr('src', url).attr('id','iframe_download_report').hide().appendTo('body'); 
});

 

而對於坑2,

首先我需要做連續點擊的限制:

利用setTimeout設置一個觸發延時,1秒以內的連續點擊都只算做一次。但是事實上很少會有這樣的惡意點擊,這種控制就很顯得很雞肋。

而最重要的一點就是做到“waiting”效果,點擊下載按鈕后就禁用該按鈕,同時按鈕文本顯示“下載中”,等到瀏覽器開始下載,再啟用該按鈕,重置按鈕文本。

所以問題的關鍵就是如何監聽到文件下載。

 

最開始的思路想到了iframe的onload事件,iframe加載html頁面,確實會觸發onload事件,但是下載卻不會。又想到了異步下載,也被我否決。第二天開會的時候,我問到這個問題的解決辦法,一位后端提到他們已有解決方案就是使用cookie,豁然開朗。想到之前百度時在stack overflow上被我匆匆一瞥忽略的cookie和token,原來答案很早就有了冏rz

 

思路大致是這樣:

前端生成一個唯一的token,以get方式隨url傳給后端。后端將token寫進cookie中,而前端通過定時器獲取,然后核對前端生成的token和通過cookie獲取的token值是否一致。

生成唯一的token,這個可以用new Date()結合隨機數做:

_setFormToken:function(){
    return ""+(Math.random()*1024|0)+new Date().getTime();
}

禁用啟用鏈接,因為超鏈接不支持disabled屬性,我們可以操作它的href屬性~~

其他的就很簡單了,只要檢測到token一致,就啟用鏈接,然后移除iframe。如果沒有獲取到token或者token不一致,就繼續setTimeout。

        _iframeDownLoad:function(){
            var timer,_this=this,flag=0;
            $(document).on('click','.J_DownLog',function(){
                var downloadToken=_this._setFormToken(),
                    url=this.href+"&downloadToken="+downloadToken,
                    triggerDelay = 1000,
                    btn=$(this);

                _this._disableLink(btn,"導出中...");
                clearTimeout(timer);
                
                timer=setTimeout(function() {
                    function checkToken(){
                        sertoken=_this._getCookie( "downloadToken" );
                        if(sertoken==downloadToken){
                                clearTimeout( downloadTimer );
                                _this._expireCookie( "downloadToken" );
                                frame.remove();
                                _this._enableLink(btn,"導出日志");
                                flag=0;
                        }else{
                            checkToken();
                        }
                    }
                    if(!flag){
                        flag=1;
                        var frame=$('<iframe />').attr('src', url).attr('id','iframe_download_report').hide().appendTo('body'); 
                        var downloadTimer=setTimeout(checkToken,1000);                        
                    }

                }, triggerDelay);
                return false;
                
            });
        }

 -----------------后續------------------

2015.04.28

 

模擬了下低網速的情況,發現瀏覽器獲取token與彈窗下載對話框之間有時間差,如果每次都是點擊導出時添加新的iframe/導出后移除iframe,就會產生iframe過早移除的情況,這樣下載對話框就彈不出來了。所以,需要修改為第一次生成iframe,之后都是修改iframe的地址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM