【问题标题】:Perform page navigation after a file download文件下载后执行页面导航
【发布时间】:2013-06-05 01:57:11
【问题描述】:

我需要找到一种在生成文件下载后执行页面导航的方法。到目前为止,我已经准备好文件下载并正常工作:

FileInputStream stream = new FileInputStream(file);
        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ec = fc.getExternalContext();
        ec.responseReset();
        ec.setResponseContentType("application/octet-stream");
        ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        OutputStream out = ec.getResponseOutputStream();

        byte[] outputByte = new byte[4096];

        while(stream.read(outputByte, 0, 4096) != -1)
        {
                out.write(outputByte, 0, 4096);
        }
        stream.close();
        out.flush();
        out.close();
        fc.responseComplete();

到目前为止,我已经尝试从 ExternalContext 重定向,但我得到了 IllegalStateException。

ec.redirect(url)

我还尝试将所有以前的代码包装在一个字符串方法中,该方法返回最后要导航的页面。那也没用。

有什么建议吗?

【问题讨论】:

  • 上次我不得不做类似的事情时,我将文件下载委托给一个普通的旧 servlet,并从 javascript window.open 调用它。也许有更优雅的方式来做到这一点。
  • 好吧,我一整天都在努力。我真的不知道有没有。
  • @dustedrob 2 建议:去掉 responseReset() 并用 responseComplete 替换它,然后调用 fc.getApplication().getNavigationHandler().handleNavigation(fc,from,destinationPage)ec.dispatch(url)
  • @kolossus OP 在使用要下载的文件完成响应后使用 fc.responseComplete。如果你之前完成了响应,你会得到错误。
  • AFAIK 以干净的方式下载文件后无法重定向。您最好的选择是在执行表单提交后进行重定向。另一种方法是来自@SJuan76 的示例。

标签: jsf navigation download


【解决方案1】:

您不能对 1 个请求返回 2 个响应。您只能对 1 个请求返回 1 个响应。文件下载计为一个响应,重定向计为另一个响应。

您最好的选择是返回一个响应,该响应会以某种方式自动启动一个新请求。然后可以将第二个响应返回到这个自动发起的请求。 JavaScript 在这方面非常有用,例如window.location(在当前窗口中触发新请求)、window.open()(在新窗口中触发新请求)和form.submit()(提交 POST 表单)。

最简单的方法是重定向到目标页面,其中一些 JavaScript 有条件地呈现(并立即执行),进而触发文件下载,例如window.locationform.submit()。如果下载本身已设置为附件,则window.open() 不合适。请注意,此方法不会在用户保存文件下载后 重定向,这显然是不可能的,因为在保存下载的最后一位时没有客户端事件可以挂钩。相反,首先执行重定向,然后执行文件下载。

如果您在这方面确实有困难,那么您始终可以创建一个小程序或 webstart 应用程序来完全管理下载文件的保存,这样您就可以在保存最后一位后轻松执行重定向。然而,这在 IMO 中显得很笨拙(甚至可能对 UX 不利;例如,我个人讨厌几个网站上的这种“下载管理器”)。

【讨论】:

  • 好的,我会试一试并报告。谢谢!
【解决方案2】:

感谢@BalusC 我做到了!从第一页开始,我只是执行导航,在着陆页上我包含以下代码:

           <c:if test="#{bean.readyForDownload}">
                <script>
                window.onload = function() {
                    document.getElementById('form:link').onclick();
                }
                </script>


            <h:form id="form">
                <h:commandLink id="link" action="#{bean.prepareFileDownload()}"/>
            </h:form>
           </c:if>

【讨论】:

  • 您能否更详细地解释一下您是如何在下载文件后将用户引导至 pdf 的?
猜你喜欢
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多