在新选项卡/窗口中打开/下载文件时刷新/导航当前页面

时间:2013-08-20 10:59:30

标签: javascript jsf primefaces download new-window

我有一个按钮,可以打开一个带有生成的pdf文件的新标签。 但是,在我点击按钮后,我想导航到另一个页面。

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

这是我的代码:

<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文件,我认为这是问题:

    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 个答案:

答案 0 :(得分:3)

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

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

这是一个启动示例:

初始形式:

<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(为简洁起见省略了nullchecks等;假定为Files#copy()的Java 7):

@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());
    }

}

答案 1 :(得分:1)

正如BalusC所说,Refresh/navigate current pageopening downloading file是两种不同的回应,必须有两次回复。我遇到了类似的问题。我成功地用jsf ajax解决了它。

这是我的代码的一部分:

XHTML:

<h:commandButton id="download-button" class="download-button"
    value="download">
<f:ajax event="click" execute="@form" render=":msg-area"
    listener="#{myController.checkForDownload}" onevent="checkCallBack" />
</h:commandButton>
<h:commandButton id="download-button2" class="download-button2"
    value="download" style="display: none;"
    action="#{myController.download}">
</h:commandButton>

使用Javascript:

function checkCallBack(data) {
    var ajaxStatus = data.status;
    switch (ajaxStatus) {
    case "begin":
        break;
    case "complete":
        break;
    case "success":
        document.getElementById('download-form:download-button2').click();
        break;
    }
}

download-button在页面上呈现消息区域,download-button2触发下载方法。他们是两个不同的要求。第一个请求完成后,将触发第二个请求。