spring-boot - 在 Thymeleaf 生成的 HTML 文档中包含一个
问题描述
在我的 Spring Boot 应用程序中,我正在使用 Thymeleaf 生成 HTML 电子邮件。我想<img>
在这些电子邮件中包含一个。图像存储在/src/main/resources/static/img/logo.png
.
我已经确认可以通过在本地启动应用程序并http://localhost:8080/img/logo.svg
在浏览器中请求来解析图像。
为了在 HTML 中包含这张图片,我尝试了以下所有方法
<img th:src="@{/img/logo.png}" />
<img th:src="@{img/logo.png}" />
<img th:src="@{~/img/logo.png}" />
- Base64 编码图像
<img src="data:image/png;base64,iVBORw0KGgoAA..." />
每一项的结果是:
- 抛出异常:org.thymeleaf.exceptions.TemplateProcessingException: Link base "/img/logo.svg" cannot be context relative (/...) 除非用于执行引擎的上下文实现了 org.thymeleaf.context.IWebContext 接口
- 呈现
<img src="img/logo.png" />
在电子邮件中显示为损坏的图像 - 呈现
<img src="/img/logo.png" />
在电子邮件中显示为损坏的图像 - 该图像在我测试的大多数电子邮件客户端中呈现,但被 GMail 阻止,并且无法通过设置解除阻止。
我想为了使图像在电子邮件中正确呈现,我需要提供一个绝对 URL,但我不确定如何实现。
部分问题在于,电子邮件未显示是因为 URL 不正确,还是因为电子邮件客户端阻止了图像,这一点并不明显。
更新
我认为这很明显,但显然不是:我不能使用任何将主机名硬编码为的解决方案,localhost:8080
因为这只是我在本地运行时使用的 URL,而且我还需要它在其他环境中工作,例如 prod
解决方案
先进的
您引入了一个声明“公共 url”的属性(例如 in application.properties
):
public_domain=http://somwhere.com
像这样使用它:
<img th:src="@{|${public_domain}/img/logo.svg|}" />
喜欢这里。
完全动态
<img th:scr="${#httpServletRequest.scheme}+'://'+${#httpServletRequest.serverName}+':'+${#httpServletRequest.serverPort}+@{img/logo.svg}" />
超级酷!(这仅在存在 http(servlet)请求时才有效,这在此处似乎不相关。)
更深入
您永远不知道谁使用任何客户端“监视”您的电子邮件(信任任何服务器..并从中加载图像)!!?...
因此,在 html 电子邮件中嵌入图像是 [so] 中的一个“非常流行”的问题。
并应用于百里香:他们为此有额外的文章!(还显示 img 附件 ..适用于 html 和文本(无图像;()!!!;)
总结一下(一旦配置了邮件和模板):
模板:
<img src="sample.png" th:src="|cid:${imageResourceName}|" />
img 元素有一个硬编码的 src 值——非常适合原型设计——在运行时将被类似 cid:image.jpg 之类的东西替换为与附加图像文件名匹配的内容。
服务:
String imageResourceName = ...
byte[] imageBytes = ...
String imageContentType = ...
// Prepare the evaluation context
final Context ctx = new Context(locale);
...
ctx.setVariable("imageResourceName", imageResourceName); // so that we can reference it from HTML
// Prepare message using a Spring helper
final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
final MimeMessageHelper message = ...
message.set...
// Create the HTML body using Thymeleaf
final String htmlContent = ...
// Add the inline image, referenced from the HTML code as "cid:${imageResourceName}" !!!
final InputStreamSource imageSource = new ByteArrayResource(imageBytes);
message.addInline(imageResourceName, imageSource, imageContentType);
// Send mail ...
推荐阅读
- subset - 为什么在对数据框进行子集化后我得到 0 个观察值
- javascript - 是否有使图像不可点击的功能,以使默认的 chrome 小部件不会出现并允许他们下载图像?
- javascript - 使用带有 JavaScript 模板文字函数的 for 循环
- join - 如何加入两个选项
> - mysql - MySQL vs MSSQL INSERTs 速度测试
- ruby-on-rails - 在框架“ruby”中没有找到头文件“config.h”?
- python - 计算 2 个数据帧之间的最小距离并估计一个数据帧中的缺失点位置
- html - 响应式网页设计栏出现在下方
- visual-studio-code - 有没有办法删除 VSCODE 中的所有键绑定?
- mysql - Q: MYSQL 数据表突然丢失