1. 程式人生 > >檔案下載(例如EXCEL匯出)優化之防止使用者多次操作

檔案下載(例如EXCEL匯出)優化之防止使用者多次操作

  1. 問題簡介
     在專案中客戶提出優化一下系統的匯出excel功能,由於有時候資料量比較大,伺服器查詢資料和生成檔案的事件可能會比較長,所以促使在匯出excel時頁面可能會長時間沒反應,使用者可能會以為系統卡頓就頻繁點選匯出按鈕。那麼我們需要在此期間不讓使用者重複操作,當檔案生成好了並且下載完成之後,才讓使用者可以繼續操作,否則就讓按鈕置灰。
  2. 簡單分析
    正常情況這種時候首先想到的就是用ajax向伺服器提交資料,並限制使用者的頁面操作,得到伺服器返回的成功狀態之後再解除操作限制就行了,但是後來發現ajax不支援流型別資料,而下載檔案就是用的流,所以這裡只能使用submit,而submit在這裡就有個問題,我們怎麼才能知道伺服器什麼時候已經生成好了excel,並且下載到瀏覽器中呢?也就是我們什麼時候確定可以解除對使用者的操作限制?所以這個問題就變成了得到伺服器的狀態反饋。
  3. 實現的邏輯
     ⑴方案簡介
          直接submit資料到後臺,後臺處理完成之後往cookie裡面寫值,而前臺通過不停讀取cookie中的值,
          如果得到了伺服器寫入的值,就證明後臺已經處理完了,這時候就可以接觸頁面操作限制了。
     ⑵具體實現邏輯
          a:當我們進入匯出的方法時,首先將匯出按鈕設定置灰屬性
          b:生成一個cookieKey,這個就是cookie的name值,我這裡生成的方法是
                cookieKey = 登入人ID+UUID.randomUUID.toString().replace("-","");
          c:將生成的coookieKey的值放到form表單中,然後使用formde submit()方法將資料提交到後臺。
          d:資料提交到後臺時,後臺需要建立cookie物件,並且將cookie放到response中,讓response傳回前臺
                 注意:
                       ①建立cookie
                             Cookie cookie = new Cookie(cookieKey,cookieValue);//cookieValue值隨意,隨機數UUID即可。
                             cookie.setMaxAge(60*60);//時間為一天
                             cookie.setPath("專案的根路徑即可");
                             //將cookie放到response中。最後這個response將這個cookie隨著下載excel一起寫到瀏覽器
                             response.addCookie(cookie);
          e:在前端js中form.submit()提交方法之後,使用方法window.setTimeout(getCookie(cookieKey),1000);
                這個方法就是,在1秒後呼叫一個js中的function名稱為getCookie方法,引數為cookie的name。注意:
               form的submit方法是一個非同步請求,所以我們間隔一秒比較好。那麼在getCookie方法中我們傳送一個
               ajax到後臺去獲取我們建立的cookie,如果excel下載完成,那麼我們的前臺瀏覽器上肯定是存在這個創
               建的cookie的,如果成功獲取到就返回成功,前臺就將之前置灰的按鈕放開,並停止傳送ajax,並且最好將
               這個建立的cookie刪除,避免每一次下載都建立一個cookie。因為它的作用就是一個標識,作用完成之後
               就可以刪除了。如果沒有獲取到,前端就使用遞迴方法反覆傳送ajax請求到後臺。
               具體如下
                  ① ajax方法
                        function getCookie(cookieKey){
                            $.ajax(function(){
                                  url:"".
                                  method:"",
                                  ....,
                                  success:function(data){
                                          if(data.success){
                                               //1:放開按鈕,清除置灰效果
                                              //2:清除建立的cookie
                                               var d = new Date(0).toUTCString();
                                               var expires = "expires="+d+" ;path=設定的cookie路徑";
                                               document.cookie = cookieKey+"="+";"+expires;
                                                return;
                                          }  
                                         //如果沒有獲取到就遞迴呼叫自身
                                         window.setTimeout(getCookie(cookieKey),1000);
                                   }
                              })}

                         ②後端獲取cookie的方法,其實就是前段request傳遞過來的
                             
              

文章目錄