我有一个按钮,可以打开一个带有生成的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();
答案 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 page
和opening 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
触发下载方法。他们是两个不同的要求。第一个请求完成后,将触发第二个请求。