2014-05-08 52 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