开发者

Can't create a PDF with iText and JSF

开发者 https://www.devze.com 2023-04-09 19:50 出处:网络
I want to create a pdf using iText in my JSF + Spring web app. When I click on a button the pdf should be generated. The method that is fired:

I want to create a pdf using iText in my JSF + Spring web app. When I click on a button the pdf should be generated. The method that is fired:

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 ByteArrayOu开发者_Python百科tputStream 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()");
}

this is the page with the button:

<!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>

I see the debug messages in the log but nothing happens to the web app. I don't see a pdf. What am I doing wrong?

Regards,

Derk

EDIT: When I changed the <a4j:commandButton /> to a <h:commandButton /> it worked.


I've never used RichFaces, but with Primefaces controls, you can set the attribute ajax="false".

<p:commandButton id="someid" value="Text for user" action="someConfiguredAction"  ajax="false"/>

or

<h:commandButton id="someid" value="Text for user" action="someConfiguredAction"/>


When you use <a4j:commandButton> a new XmlHttpRequest will be created on your browser, and your serverside method will be called via JS. The output PDF will be written into the output stream, but the actual result will be read out of XmlHttpRequest, and interpreted by jsf.ajax.response() javascript function.

Since JSF ajax responses are always XML with a root of <partial-response>, you're basically sending junk back to the JSF ajax handler. (PDF != XML with <partial-response> root). Obviously this fails parsing so it appears that "nothing happens".

So you must use the <h:commandButton/> to do a real request. You need also to do:

response.setHeader("Content-disposition", "attachment; filename=mycool.pdf");

serverside in order to inform the browser that it receives a new file, and should download it, and not display it instead of the page.

This will have the end behavior of an "ajax" call, where you do a call, you receive the response (and save it), but your page content stays there.


You can't download files with ajax. Ajax is fired and handled by JavaScript code. However, JavaScript has for obvious security reasons no way to force a Save As dialogue with arbitrary content in a JavaScript variable (such as the response of an ajax request).

Make sure that the download button fires a synchronous (non-ajax) request. Use a normal command button or turn off ajax in the ajax command button.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号