使用XSL样式表将JSON转PDF时图片无法显示的问题求助
问题分析与解决办法
你遇到的问题核心是ITextRenderer无法解析相对路径的图片——虽然转换后的HTML在浏览器里能正常显示,但ITextRenderer渲染PDF时,需要明确知道资源的基准路径(Base URL),否则它找不到相对路径指向的图片文件。
主要原因
- 基准URL未设置:你调用
renderer.setDocument(resultDoc, "");时第二个参数为空,ITextRenderer无法确定./img/logo.png这个相对路径的起始位置,自然找不到图片。 - 运行时资源路径变化:开发时图片在
src/main/resource/img,但程序运行(尤其是打包后)时,这个目录的实际路径可能和开发环境不一致,导致相对路径失效。
解决办法
方法1:设置正确的基准URL(推荐)
通过类加载器获取资源目录的绝对URL,作为ITextRenderer的基准路径,让它能正确解析相对路径的图片。修改Java代码中renderer.setDocument的部分:
// 获取img目录的URL(从classpath中读取) URL resourceBase = YourClassName.class.getResource("/img/"); if (resourceBase != null) { // 设置基准URL,指导ITextRenderer查找资源的起始位置 renderer.setDocument(resultDoc, resourceBase.toExternalForm()); } else { throw new RuntimeException("无法找到img资源目录,请检查文件位置"); }
同时调整XSL中的img路径,去掉./,直接使用logo.png(因为基准URL已经指向/img/目录):
<td> <img> <xsl:attribute name="src">logo.png</xsl:attribute> </img> </td>
方法2:嵌入Base64编码的图片(更可靠,适合打包场景)
如果程序需要打包成JAR/WAR,依赖外部文件路径容易出问题,这时可以将图片转换成Base64编码嵌入HTML,完全脱离外部文件依赖。
先在Java中读取图片并转Base64,再传递给XSL作为参数:
// 读取图片并转换为Base64编码 byte[] imageBytes = Files.readAllBytes(Paths.get(getClass().getResource("/img/logo.png").toURI())); String base64Image = Base64.getEncoder().encodeToString(imageBytes); // 将Base64字符串传入XSL作为参数 transformer.setParameter("logoBase64", base64Image);
然后在XSL中使用这个参数:
<td> <img src="data:image/png;base64,{$logoBase64}" /> </td>
方法3:使用绝对文件路径(仅适合开发调试)
开发阶段可以用绝对路径快速验证:
<td> <img> <xsl:attribute name="src">C:/your-project-path/src/main/resources/img/logo.png</xsl:attribute> </img> </td>
注意:这种方法不适合生产环境,因为路径会随部署环境变化。
额外检查
- 确认
logo.png确实存在于运行时的资源目录中(打包后可检查JAR/WAR是否包含该文件)。 - 确保
flying-saucer-pdf(ITextRenderer所属库)和依赖的iText版本兼容,建议使用最新稳定版。
内容的提问来源于stack exchange,提问作者user8352964
相关产品推荐
相关产品推荐

