Spring Can';t使用iText和JSF创建PDF

Spring Can';t使用iText和JSF创建PDF,spring,jsf,jsf-2,itext,Spring,Jsf,Jsf 2,Itext,我想在我的JSF+SpringWeb应用程序中使用iText创建pdf。 当我点击一个按钮时,应该会生成pdf。激发的方法: public void createPDF() { log.debug("entered createPDF"); FacesContext context = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse)contex

我想在我的JSF+SpringWeb应用程序中使用iText创建pdf。 当我点击一个按钮时,应该会生成pdf。激发的方法:

public void createPDF() {
    log.debug("entered createPDF");
    FacesContext context = FacesContext.getCurrentInstance(); 
    HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();  
    response.setContentType("application/pdf");  
    response.setHeader("Content-disposition",  "inline=filename=file.pdf");
    try {

        // Get the text that will be added to the PDF
        String text = "test";
        // step 1
        Document document = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph(text));
        // step 5
        document.close();

        // setting some response headers
        response.setHeader("Expires", "0");
        response.setHeader("Cache-Control",
            "must-revalidate, post-check=0, pre-check=0");
        response.setHeader("Pragma", "public");
        // setting the content type
        response.setContentType("application/pdf");
        // the contentlength
        response.setContentLength(baos.size());
        // write ByteArrayOutputStream to the ServletOutputStream
        OutputStream os = response.getOutputStream();
        baos.writeTo(os);
        os.flush();
        os.close();
        log.debug("flushed and closed the outputstream");

    }
    catch(DocumentException e) {
        log.error("error: "+e);
    }
    catch (IOException e) {
        log.error("error: "+e);
    }
    catch (Exception ex) {
        log.debug("error: " + ex.getMessage());
    }
    context.responseComplete();
    log.debug("context.responseComplete()");
}
这是带有按钮的页面:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:s="http://jboss.org/seam/faces"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    template="/pages/layout/layout.xhtml">

<ui:define name="content">
        <h:form>
            <rich:panel style="width: 785px; height: 530px; ">
<a4j:commandButton value="Afdrukken" execute="@form"
                    action="#{huishoudinkomenAction.print}" style="float:right;" />

        </rich:panel>
    </h:form>
</ui:define>

我在日志中看到调试消息,但web应用程序没有发生任何变化。我没有看到pdf。 我做错了什么

问候,

德克

编辑: 当我将
更改为
时,它工作了。

当您使用
时,将在浏览器上创建一个新的XmlHttpRequest,并通过JS调用您的服务器端方法。输出PDF将写入输出流,但实际结果将从XmlHttpRequest中读取,并由
jsf.ajax.response()
javascript函数解释

由于JSF ajax响应始终是根为
的XML,因此基本上是将垃圾发送回JSF ajax处理程序。(PDF!=带有
根目录的XML)。显然,这无法解析,因此看起来“什么也没发生”

因此,您必须使用
来执行真正的请求。您还需要执行以下操作:

response.setHeader("Content-disposition", "attachment; filename=mycool.pdf");
服务器端,以通知浏览器它接收到新文件,并应下载该文件,而不是显示该文件而不是页面

这将有一个“ajax”调用的结束行为,即您进行调用,您收到响应(并保存响应),但您的页面内容仍保留在那里。

当您使用
时,将在浏览器上创建一个新的XmlHttpRequest,并通过JS调用您的服务器端方法。输出PDF将写入输出流,但实际结果将从XmlHttpRequest中读取,并由
jsf.ajax.response()
javascript函数解释

由于JSF ajax响应始终是根为
的XML,因此基本上是将垃圾发送回JSF ajax处理程序。(PDF!=带有
根目录的XML)。显然,这无法解析,因此看起来“什么也没发生”

因此,您必须使用
来执行真正的请求。您还需要执行以下操作:

response.setHeader("Content-disposition", "attachment; filename=mycool.pdf");
服务器端,以通知浏览器它接收到新文件,并应下载该文件,而不是显示该文件而不是页面


这将有一个“ajax”调用的结束行为,即您执行一个调用,您收到响应(并保存),但您的页面内容仍保留在那里。

我从未使用过RichFaces,但使用Primefaces控件,您可以设置属性ajax=“false”



我从未使用过RichFaces,但是使用Primefaces控件,可以设置属性ajax=“false”



不能使用ajax下载文件。Ajax由JavaScript代码触发和处理。然而,出于明显的安全原因,JavaScript无法强制与JavaScript变量中的任意内容(例如ajax请求的响应)进行另存为对话


确保下载按钮触发同步(非ajax)请求。使用普通命令按钮或在ajax命令按钮中关闭ajax。

您不能使用ajax下载文件。Ajax由JavaScript代码触发和处理。然而,出于明显的安全原因,JavaScript无法强制与JavaScript变量中的任意内容(例如ajax请求的响应)进行另存为对话


确保下载按钮触发同步(非ajax)请求。使用普通命令按钮或在ajax命令按钮中关闭ajax。

(哎呀,这应该是bogdan.mustiata答案的补充)(哎呀,这应该是bogdan.mustiata答案的补充)
<h:commandButton id="someid" value="Text for user" action="someConfiguredAction"/>