2014-05-08 56 views
0

我想創建一個鏈接,該鏈接將啓動與頁面本身異步的文件下載,即我希望頁面在文件下載過程中不被鎖定。我應該讓它在門外發起嗎?或者是否有一些內部檢票允許我建立一個繞過頁面鎖的資源流?Apache Wicket:無法鎖定頁面的文件下載

事情我想:

  • DownloadLink - 鎖定頁面,在其文檔說明。這是我的出發點。

  • ResourceLink - 沒有在doc中明確聲明鎖定,所以我嘗試了這一點,但它也鎖定了頁面。

  • 在這一點上,我已經調查了兩個鏈接的代碼有點,並注意到他們都通過ResourceStreamRequestHandler安排下載。期待他的這種行爲可能只是處理程序,具體的我已經嘗試安排我寫了一個自定義處理程序:

    private void sendFile(final File file) throws IOException { 
    
        IRequestHandler fileDownloadHandler = new IRequestHandler() { 
         @Override 
         public void respond(IRequestCycle requestCycle) { 
          WebResponse response = (WebResponse) requestCycle.getResponse(); 
    
          OutputStream outStream = response.getOutputStream(); 
          response.setContentType("audio/x-wav"); 
          response.setContentLength((int)file.length()); 
    
          String fileName = "Somethingsomething.wav"; 
    
          // sets HTTP header 
          response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); 
    
          byte[] byteBuffer = new byte[1024]; 
          DataInputStream in = null; 
    
          try { 
    
           in = new DataInputStream(new FileInputStream(file)); 
    
           int length = 0; 
           // reads the file's bytes and writes them to the response stream 
           while ((in != null) && ((length = in.read(byteBuffer)) != -1)) 
           { 
            outStream.write(byteBuffer,0,length); 
           } 
    
           in.close(); 
           outStream.close(); 
    
          } catch (IOException e) { 
           throw new PortalError("IOException trying to write the response", e); 
          } 
         } 
    
         @Override 
         public void detach(IRequestCycle requestCycle) { 
    
         } 
        }; 
    
        getRequestCycle().scheduleRequestHandlerAfterCurrent(fileDownloadHandler); 
    
    } 
    
  • 這並沒有完全奏效,所以我進一步調查。我注意到,與我預期的不同,「預定的」請求處理程序不會按照我的預期在單獨的請求上執行,而是在同一個請求上執行。我認爲它必須是第一個處理程序的頁面被鎖定,然後在第二個處理程序執行時保持鎖定狀態。所以,我試圖強迫下載處理成一個單獨的請求(通過Ajax的行爲):

    public void startDownload(AjaxRequestTarget target) throws DownloadTargetNotFoundException{ 
    
        target.appendJavaScript("setTimeout(\"window.location.href='" + getCallbackUrl() + "'\", 100);"); 
    
    } 
    
    @Override 
    public void onRequest() { 
    
        sendFile(getFile()); 
        logger.debug("Download initiated"); 
    
    } 
    

    我發現這個here,並希望它可能是什麼,我一直在尋找。然而,毫不奇怪的是,頁面仍然被鎖定(我會想象因爲仍然必須從頁面中檢索行爲,爲此必須獲取頁面鎖定)。

我很茫然,我應該看下一個,特別是在所有這一次試圖獲得一個簡單的下載鏈接工作。我正在考慮在wicket之上創建另一個web過濾器,這可以在wicket中發出信號以在wicket過濾器完成其工作後創建下載(並且因此頁面鎖已經被釋放),但是這似乎有點過分像這樣的任務。

歡迎任何建議。

+0

這只是看起來過度設計,如果你問我。 1)創建可以將文件轉儲到響應的servlet(google:java FileServlet)。 2)創建該servlet的鏈接/按鈕。 3)用戶點擊鏈接/按鈕,瀏覽器完成剩下的工作。經典解決方案,完美無瑕。 – Gimby

+0

由於幾個原因,解決方案不夠靈活。首先,我必須在按鈕/鏈接點擊上生成文件(頁面上可能有太多的預先生成它們),這需要額外的依賴性和在新的servlet中的處理。可以解決這個問題,但我也不喜歡在檢票門外有任何組件的想法,因爲那樣我就失去了使用檢票的好處(即我無法訪問頁面上的其他組件)。 – WiseTree

回答

0
+0

這看起來正是我一直在尋找的東西。我會嘗試一下,並接受如果我能得到它的工作。 – WiseTree

+1

這需要一些額外的工作(你鏈接的資源略有跳過,如果我沒有事先做過研究,我不認爲我能理解這些),但我已經運行了。我想我可以用一些額外的信息修改你的答案,如果我能弄清楚如何正確地格式化它。 – WiseTree