4

Print Image in PDF using Flying saucer.

HTML code:

<?xml version="1.0" encoding="utf-8" ?>
<html>
    <p>
        <img src="Smallcheck.jpg" width="20" height="21"/>
    </p>
</html> 

When I convert the HTML to PDF using Flying Saucer. The generated PDF is not printing the images.

var outputForPdfStream = new this.ByteArrayOutputStream();

// tidy the html
var domdoc =  this.domDocument;
var iTidy = new this.tidy();
iTidy.setShowWarnings(false);
iTidy.setXmlTags(false);
iTidy.setInputEncoding("UTF-8");
iTidy.setOutputEncoding("UTF-8");
iTidy.setXHTML(true);//
iTidy.setMakeClean(true);
domdoc = iTidy.parseDOM(inputStream, outputForPdfStream);

// Convert the document to XHTML panel and then rendering it into a PDF
var xhtmlPanel = new this.XHTMLPanel();
xhtmlPanel.setDocument(domdoc);

var renderer = new this.iTextRenderer();
renderer.setDocument(xhtmlPanel.getDocument(), null);
renderer.layout();
renderer.createPDF(bos);
bos.flush();
inputStream.close();
this.debug("INPUT STREAM" + inputStream);

var byteArray = bos.toByteArray();
var encodedString  = this.StringUtil.base64Encode(byteArray);
this.debug("Encoded String" + encodedString);

Do I need to use any specific package to print image in PDF. Please let me know if you have any questions.

Sebastian Brosch
  • 42,106
  • 15
  • 72
  • 87
john will
  • 53
  • 1
  • 6

2 Answers2

4

In order to embed an image in a PDF generated by Flying Saucer,

1) Convert the image to a base64 encoded string.

Path path = Paths.get("src/main/resources/static/images/mastercard.png");
String base64Image = convertToBase64(path);

Function to convert image stored in a path like shown above, to a base64 encoded string

private String convertToBase64(Path path) {
    byte[] imageAsBytes = new byte[0];
    try {
      Resource resource = new UrlResource(path.toUri());
      InputStream inputStream = resource.getInputStream();
      imageAsBytes = IOUtils.toByteArray(inputStream);

    } catch (IOException e) {
      System.out.println("\n File read Exception");
    }

    return Base64.getEncoder().encodeToString(imageAsBytes);
  }

2) Set the base64 encoded image in the thymeleaf context

    Context context = new Context();
    String image = "data:image/png;base64, " + base64Image;
    context.setVariable("image",  image);

    String html = templateEngine.process("template", context);

3) In HTML, set the value of image as shown below:

<img th:src="${image}" style="width: 200px; height=100px"/>

4) Finally, render the HTML template to PDF

  ITextRenderer renderer = new ITextRenderer();
  renderer.setDocumentFromString(html); // html -> String created in Step 2
  renderer.layout();
  final ByteArrayOutputStream baos = new ByteArrayOutputStream();
  renderer.createPDF(baos)

Now you have the byteArrayOutputStream of the generated PDF, with which you can choose to store them to a file server or serve it to a client in a format of your choice.

  • 7
    Please note, since flying saucer switched to java.util.Base64 instead of javax.xml.bind.DatatypeConverter in v9.1.20, a `data:image/png;base64,` tag is not rendered anymore if the data string starts with a leading space. – Michael Nov 04 '20 at 13:36
  • This comment saved me a lot of effort. I was about to create a ReplacedElementFactory for this but then I switched the version from v9.1.18 to v9.1.2x and it worked! – superigno Nov 19 '21 at 00:58
0

You need to set the context and relative path for your image,

renderer.setDocument(xhtmlPanel.getDocument(), null);

should change to ,

renderer.setDocument(xhtmlPanel.getDocument(), "http:\\mywebsite:8080\images");

And your images should be under the folder specified in context , you can use relative path for your images in src,

<?xml version="1.0" encoding="utf-8" ?>
<html>
    <p>
        <img src="check/Smallcheck.jpg" width="20" height="21"/>
    </p>
</html> 
Avinash Singh
  • 3,421
  • 2
  • 20
  • 21