在使用Spring Boot、飞碟和Thymeleaf制作PDF模板时,图片无法显示。

IT小君   2023-09-16T19:49:15

我使用Spring Boot,flying saucer和thymeleaf从HTML模板创建PDF文件。但是我的文件中的图片无法显示。

项目结构:

项目结构

HTML代码:

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

当我把img标签改成:

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

当我创建PDF文件时,出现错误:

org.thymeleaf.exceptions.TemplateProcessingException: 链接基础路径 "static/images/mastercard.png" 不能是上下文相对路径 (/) 或页面相对路径,除非你实现org.thymeleaf.context.IWebContext接口(上下文的类是: org.thymeleaf.context.Context)

评论(5)
IT小君

尝试使用Spring的classpath:前缀。这会直接从类路径加载您的文件,无论您是从.jar文件还是从您的IDE中运行。这是一个示例:

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

有关classpath:的更多信息可以在官方文档中找到。

2023-09-16T19:49:23   回复
IT小君

为了将图像嵌入Flying Saucer生成的PDF中,

1)将图像转换为base64编码的字符串。

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

将上述路径中存储的图像转换为base64编码的字符串的函数

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文件读取异常");
    }

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

2)在thymeleaf上下文中设置base64编码的图像

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

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

3)在HTML中,将图像的值设置如下:

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

4)最后,将HTML模板渲染为PDF

  ITextRenderer renderer = new ITextRenderer();
  renderer.setDocumentFromString(html); // html -> 在步骤2中创建的字符串
  renderer.layout();
  final ByteArrayOutputStream baos = new ByteArrayOutputStream();
  renderer.createPDF(baos)

现在您有了生成的PDF的byteArrayOutputStream,您可以选择将其存储到文件服务器或以您选择的格式提供给客户端。

2023-09-16T19:49:43   回复
IT小君

使用标准的HTML src属性和相对路径,从项目的根目录开始。

你可以把你的图片放在项目的根目录中,并像这样使用:

<img src="mastercard.png" />

如果你想使用资源文件夹,可以这样设置:

<img src="src/main/resources/static/images/mastercard.png" />
2023-09-16T19:49:53   回复
IT小君

我遇到了同样的问题,但是从磁盘读取图像文件会有一些成本,我建议你使用uri-data

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

因为你无论如何都要读取图像来生成PDF,最好将其保存在模板中。

2023-09-16T19:49:59   回复
IT小君

@sangeethapradeep的回答对我来说基本有效,只是我需要将SVG图像转换为Base64。所以我使用了https://pixelied.com/convert/svg-converter/svg-to-base64来将我的图像转换为Base64,并在代码中包含了它,结果很好。

2023-09-16T19:50:03   回复