本文介绍了在新选项卡/窗口中打开/下载文件时刷新/导航当前页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个按钮,可以打开一个带有生成的 pdf 文件的新选项卡.但是,单击按钮后,我想导航到另一个页面.

I have a button which opens a new tab with a generated pdf-file.However, after I click on the button, I want to navigate to another page.

这意味着,在单击按钮后,我想打开一个带有 pdf 的新标签页并导航到初始标签页上的另一个页面.我正在使用 primefaces p:commandButton 并尝试使用 onclick="window.location.href='www.google.de'" 但它不起作用.但是 onclick="window.lalert('www.google.de')" 确实有效.

That means, after clicking on the button i want to open a new tab with the pdf and navigate to another page on the initial tab. I am using primefaces p:commandButton and tried with onclick="window.location.href='www.google.de'" but it does not work. However onclick="window.lalert('www.google.de')" does work.

这是我的代码:

<h:form id="transForm" target="_blank">
<p:commandButton  value="Zertifikat erstellen" ajax="false"
                                label="Speichert die Anmeldung und erstellt ein Zertifikat im PDF-Format"
                                action="#{transportErfassen.generatePDFZertifikat()}"/>

</h:form>

generatePDFZertifikat() 确实使用以下代码创建了一个 pdf 文件,我认为这是问题所在:

generatePDFZertifikat() does create a pdf-File with following code, I think here is the issue:

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();

    externalContext.setResponseContentType("application/pdf" );
    externalContext.setResponseHeader("Expires", "0");
    externalContext.setResponseHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
    externalContext.setResponseHeader("Pragma", "public");
    externalContext.setResponseHeader("Content-disposition", "inline; filename="" + fileName +""");
    externalContext.setResponseContentLength(out.length);
    externalContext.addResponseCookie(Constants.DOWNLOAD_COOKIE, "true", new HashMap<String, Object>());

    //setze explizit auf OK
    externalContext.setResponseStatus(200);

    OutputStream os = externalContext.getResponseOutputStream();
    os.write(out, 0, out.length);
    os.flush();

    facesContext.responseComplete();
    facesContext.renderResponse();

推荐答案

您基本上是在尝试将 2 个响应发送回 1 个请求.这永远不会在 HTTP 中工作.如果你想发回 2 个响应,你必须让客户端以某种方式触发 2 个请求.您已经在寻找解决方案的正确方向,几乎不需要 JavaScript 的帮助,就可以在单个事件(单击)上触发多个请求.然而,您在 onclick 中的尝试无效,在表单提交之前,点击提交按钮时 window.location 的更改完全中止了按钮的原始操作, 提交表单.

You're basically trying to send 2 responses back to 1 request. This is not ever going to work in HTTP. If you want to send 2 responses back, you've got to let the client fire 2 requests somehow. You were already looking in the right direction for the solution, with little help of JavaScript it's possible to fire multiple requests on a single event (click). Your attempt in onclick is however not valid, the change of window.location on click of the submit button, right before the form submit, completely aborts the original action of the button, submitting the form.

你最好的办法是直接导航到结果页面,然后在页面加载时调用 JavaScript window.open(),指向你想打开的 PDF 文件的 URL.即不可能将一些 HTML/JS 代码与指示导航的 PDF 文件一起发送(因为这显然会损坏 PDF 文件).这也意味着,您不能将 PDF 直接返回到表单提交请求.必须以这样的方式重新设计代码,以便可以通过后续的 GET 请求检索 PDF.最好的方法是使用一个简单的 servlet.您可以将生成的 PDF 临时存储在磁盘或会话中,与唯一键关联,并将该唯一键作为请求路径信息或参数传递给 window.open() URL 中的 servlet.

Your best bet is to directly navigate to the result page which in turn invokes JavaScript window.open() on page load, pointing to the URL of the PDF file which you'd like to open. It's namely not possible to send some HTML/JS code along with the PDF file instructing a navigation (as that would obviously corrupt the PDF file). This also means, that you can't return the PDF directly to the form submit request. The code has to be redesigned in such way that the PDF can be retrieved by a subsequent GET request. The best way is to use a simple servlet. You could store the generated PDF temporarily on disk or in session, associated with an unique key, and pass that unique key as request pathinfo or parameter to the servlet in window.open() URL.

这是一个启动示例:

初始形式:

<h:form>
    ...
    <p:commandButton ... action="#{bean.submit}" />
</h:form>

豆子:

public String submit() {
    File file = File.createTempFile("zertifikat", ".pdf", "/path/to/pdfs");
    this.filename = file.getName();

    // Write content to it.

    return "targetview";
}

目标视图:

<h:outputScript rendered="#{not empty bean.filename}">
    window.open('#{request.contextPath}/pdfservlet/#{bean.filename}');
</h:outputScript>

PDF servlet(为简洁起见省略了空检查等;Files#copy() 假定为 Java 7):

PDF servlet (nullchecks etc omitted for brevity; Java 7 assumed for Files#copy()):

@WebServlet("/pdfservlet/*")
public class PdfServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File file = new File("/path/to/pdfs", request.getPathInfo().substring(1));
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "inline; filename="zertifikat.pdf"");
        Files.copy(file.toPath(), response.getOutputStream());
    }

}

这篇关于在新选项卡/窗口中打开/下载文件时刷新/导航当前页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 05:57