我想創建一個鏈接,該鏈接將啓動與頁面本身異步的文件下載,即我希望頁面在文件下載過程中不被鎖定。我應該讓它在門外發起嗎?或者是否有一些內部檢票允許我建立一個繞過頁面鎖的資源流?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過濾器完成其工作後創建下載(並且因此頁面鎖已經被釋放),但是這似乎有點過分像這樣的任務。
歡迎任何建議。
這只是看起來過度設計,如果你問我。 1)創建可以將文件轉儲到響應的servlet(google:java FileServlet)。 2)創建該servlet的鏈接/按鈕。 3)用戶點擊鏈接/按鈕,瀏覽器完成剩下的工作。經典解決方案,完美無瑕。 – Gimby
由於幾個原因,解決方案不夠靈活。首先,我必須在按鈕/鏈接點擊上生成文件(頁面上可能有太多的預先生成它們),這需要額外的依賴性和在新的servlet中的處理。可以解決這個問題,但我也不喜歡在檢票門外有任何組件的想法,因爲那樣我就失去了使用檢票的好處(即我無法訪問頁面上的其他組件)。 – WiseTree