xhtmlrenderer creating PDFs of length 0

1.9k views Asked by At

I am new to org.xhtmlrenderer.pdf.ITextRenderer and have this problem:

The PDFs that my test servlet streams to my Downloads folder are in fact empty files.

The relevant method, streamAndDeleteTheClob, is shown below.

The first try block is definitely not a problem.

The server spends a lot of time in the second try block. No exception thrown.

Can anyone suggest a solution to this problem or a good approach to to debugging it?

Can anyone point me to essentially similar code that really works?

Any help would be much appreciated.

res.setContentType("application/pdf");

ServletOutputStream out = res.getOutputStream();

...

private boolean streamAndDeleteTheClob(int pageid,
                                  Connection con,
                                  ServletOutputStream out) throws IOException, ServletException {
   Statement statement;

   Clob htmlpage;

   StringBuffer pdfbuf = new StringBuffer();

   final String pageToSendQuery = "SELECT text FROM page WHERE pageid = " + pageid;

   // create xhtml file as a CLOB (Oracle large character object) and stream it into StringBuffer pdfbuf

  try {  // definitely no problem in this block
    statement = con.createStatement();
    resultSet = statement.executeQuery(pageToSendQuery);
    if (resultSet.next()) {
      htmlpage = resultSet.getClob(1);
    } else {
      return true;
    }
    final Reader in = htmlpage.getCharacterStream();
    final char[] buffer = new char[4096];
    while ((in.read(buffer)) != -1) {
      pdfbuf.append(buffer);
    }            
  } catch (Exception ex) {       
    out.println("buffering CLOB failed: " + ex);
  }

  // create pdf from StringBuffer

  try {
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document doc = builder.parse(new InputSource(new StringReader(pdfbuf.toString())));
    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocument(doc, null);
    renderer.layout();
    renderer.createPDF(out);
    out.close();
  } catch (Exception ex) {
    out.println("streaming of pdf failed: " + ex);

  }

  deleteClob(con, pageid);

  return false;
}
2

There are 2 answers

0
Mark Storer On

Two things I can think of.

1) If the iText document is not closed, it'll be empty. Looks like renderer.finish() will work, but createPDF(out) should do that already.

2) If there are no pages, you could get an empty doc as well... so an empty input could result in a 0-byte PDF.

3) You might be getting a perfectly valid PDF that's not being streamed properly. Try writing to a ByteArrayOutputStream and checking the length there.

4) An almost fanatical dedication to the Pope!

2
Adam On

Using the DocumentBuilder.parse this way will try to resolve the DTD referenced in the XHTML page. It takes a really long time. The easyest way to aviod that if you are using the Flying Saucer (xhtmlrenderer), is to create the document this way:

Document myDocument = XMLResource.load(myInputStream).getDocument();

Note that you can use XMLResource.load with a Reader too.