我想创建一个链接,该链接将启动与页面本身异步的文件下载,即我希望页面在文件下载过程中不被锁定。我应该让它在门外发起吗?或者是否有一些内部检票允许我建立一个绕过页面锁的资源流?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