6

I create a file pdf from html template using Spring Boot, flying saucer, thymeleaf. But image is not displaying in my file.

Project structure:

Project structure

code html:

<div class="col-xs-6 invoice-col-2">
   <img src="../static/images/mastercard.png" alt="mastercard"></img>
</div>

When I change img tag to:

<img src="../static/images/mastercard.png" alt="mastercard" th:src="@{static/images/mastercard.png}"></img>

When I create PDF file, I get an error:

org.thymeleaf.exceptions.TemplateProcessingException: Link base "static/images/mastercard.png" cannot be context relative (/) or page relative unless you implement the org.thymeleaf.context.IWebContext interface (context is of class: org.thymeleaf.context.Context)

DaveyDaveDave
  • 9,821
  • 11
  • 64
  • 77
dinhbao10t4
  • 118
  • 1
  • 1
  • 5
  • Try with absolute path or make `src="/images/mastercard.png" ` in `img`tag – Ajit Soman Sep 26 '17 at 06:28
  • thanks for response. I try change src="/images/mastercard.png" in img tag but image not display. I use mastercard in img tag and it display. I've just done it. :)) – dinhbao10t4 Sep 26 '17 at 07:31

5 Answers5

18

Try using Spring's classpath: prefix. This loads your file directly from the classpath, no matter if you are running from a .jar or within your IDE. Here is an example:

<img alt="mastercard" th:src="@{classpath:static/images/mastercard.png}" />

More information about classpath: can be found in the official documentation.

ssc-hrep3
  • 15,024
  • 7
  • 48
  • 87
3

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.

2

Use standard html src atribute and relative path from root of the project.

You can put your image in the root of the project and use it like this:

<img src="mastercard.png" />

If you want to resource folders you can set it like this:

<img src="src/main/resources/static/images/mastercard.png" />
Aleksandar
  • 636
  • 1
  • 7
  • 24
1

I faced the same issue but reading image file from disk is little costly, I would suggest you go with uri-data

http://www.tothenew.com/blog/using-data-urls-for-embedding-images-in-flying-saucer-generated-pdfs/

Because you anyway going to read image to generate PDF, better keep it in template.

LNT
  • 876
  • 8
  • 18
0

@sangeethapradeep's answer almost worked for me with the exception that I need to convert svg image to base64. So I used https://pixelied.com/convert/svg-converter/svg-to-base64 to convert my image and included in the code and it worked.

Prakhya
  • 21
  • 3