使用Flying Saucer与Thymeleaf生成PDF时静态图片无法显示
解决Flying Saucer生成PDF时无法加载classpath静态图片的问题
我之前也遇到过一模一样的问题!Flying Saucer对资源的加载逻辑和Spring Boot的静态资源管理不太兼容,直接用相对路径或者默认的绝对路径它根本找不到。下面给你几个亲测有效的解决方案:
方法一:配置ResourceResolver+Thymeleaf标准URL语法
这是最常用的方案,既能保持模板的简洁性,又能让Flying Saucer正确定位资源:
- 先修改Thymeleaf模板里的
img标签,用Thymeleaf的@{}语法生成标准化路径:
<img th:src="@{/images/logo_black.png}" />
这个语法会自动适配应用路径,但关键是要让Flying Saucer学会从classpath加载资源。
- 在生成PDF的代码中,给
ITextRenderer配置自定义的资源解析器:
ITextRenderer renderer = new ITextRenderer(); // 配置资源解析器,让Flying Saucer能读取classpath下的静态资源 renderer.getSharedContext().setResourceResolver(new ResourceResolver() { @Override public Resource getResource(String uri) throws IOException { // 去掉路径开头的斜杠,classpath资源不需要前置斜杠 if (uri.startsWith("/")) { uri = uri.substring(1); } // 从classpath加载资源,假设图片放在src/main/resources/static/images/下 InputStream resourceStream = getClass().getClassLoader().getResourceAsStream("static/" + uri); if (resourceStream == null) { return null; // 找不到资源时返回null即可 } return new InputStreamResource(resourceStream); } }); // 渲染HTML并生成PDF renderer.setDocumentFromString(processedHtml); // processedHtml是Thymeleaf渲染后的HTML内容 renderer.layout(); renderer.createPDF(outputStream);
方法二:直接使用Base64嵌入图片(适合小图片)
如果你的图片体积不大,直接把它转成Base64字符串嵌入HTML是最省心的,完全不用纠结路径问题:
- 先写一个工具类负责读取图片并转换为Base64:
import org.apache.commons.io.IOUtils; import org.springframework.stereotype.Component; import java.io.IOException; import java.io.InputStream; import java.util.Base64; @Component public class ImageBase64Util { public String getImageAsBase64(String imageFileName) throws IOException { // 路径对应src/main/resources/static/images/下的文件 InputStream inputStream = getClass().getClassLoader().getResourceAsStream("static/images/" + imageFileName); if (inputStream == null) { throw new IOException("图片不存在:" + imageFileName); } byte[] imageBytes = IOUtils.toByteArray(inputStream); return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes); } }
- 然后在Thymeleaf模板里调用这个工具类:
<img th:src="${@imageBase64Util.getImageAsBase64('logo_black.png')}" />
几个需要注意的坑
- 检查编译后的资源:确认
target/classes/static/images/下存在你的logo_black.png,Maven/Gradle默认会把src/main/resources下的文件复制到这里,如果找不到,大概率是路径写错了。 - 严格的XHTML格式:Flying Saucer对HTML格式要求很严格,模板开头一定要加上正确的DOCTYPE声明:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
- 注意大小写:Linux/Unix环境下文件名和路径是区分大小写的,别把
logo_black.png写成Logo_Black.png!
内容的提问来源于stack exchange,提问作者user7307131
相关产品推荐
相关产品推荐

