spring-boot - Heroku 类路径 FileNotFound 异常
问题描述
上下文:我有一个 Spring Boot 应用程序,我想在创建帐户后向用户发送电子邮件。我的资源文件夹中有一个 newUser.html 文件,我在其中编辑了“电子邮件”和“密码”字段,以及一些我想要发送的图像。我使用 Jsoup 执行此操作:
@Override
public void sendUserCreatedMail(CreateUserRequest createUserRequest) throws MessagingException, IOException {
//Get JavaMailSender
JavaMailSenderImpl mailSenderImpl = mailMapper.mapMailSender();
//set the html elements with Jsoup
Document doc = buildHtmlDocument(Main.class.getClassLoader().getResource("html/newUser.html").getPath());
Element loginElement = doc.getElementById("login");
Element passwordElement = doc.getElementById("password");
loginElement.text("Login: " + createUserRequest.getEmail());
passwordElement.text("Password: " + createUserRequest.getPassword());
String html = doc.toString();
// Add inline images, key + value
Map<String, String> inlineImages = new HashMap<String, String>();
if(Main.class.getClassLoader().getResource("images/rea-logo-rond.png").getPath() != null){
//Get Email images Path
String logoPath = Main.class.getClassLoader().getResource("images/rea-logo-rond.png").getPath();
inlineImages.put("logo", logoPath);
}
//Create email instance & send mail
MimeMessage mimeMessage = mailMapper.mapCreateUserRequestToSender(createUserRequest, inlineImages, html);
mailSenderImpl.send(mimeMessage);
}
在我的 IDE 中运行程序时,这一切都很好。然而,当我在 Heroku 上运行它时,我得到一个“FileNotFound”异常:
[java.io.FileNotFoundException: file:/app/rea-backend/target/rea-backend-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/html/newUser.html (No such file or directory)]
我偶然发现了这篇SO Article,但它没有适合我的情况的解决方案。我希望我可以将 newUser.html 作为 Blop 保存在我的数据库中,并且每次都获取它(尽管这并不是一个很好的解决方法..);但是“文档”构造函数的工作方式是,它需要您尝试使用的文件的 PATH 字符串,而不是实际文件本身......所需的图像也是如此。
必须有另一种方法来使用 Heroku 访问资源文件夹中的文件吗?还是我做错了什么?我不明白为什么它适用于本地,但不适用于 Heroku。
在这一点上,选择 Heroku 以外的其他平台不是一个选择。
解决方案
正如 M.Deinum 指出的那样,没有办法做到这一点,因为当这些文件被打包为 jar 时,这些图像不再是物理文件,只是 jar 中的资源。
通过遵循 M. Deinum 的建议并使用 messageHelper.addInline() (用于图像)和 InputStream 用于 html 文件,我得到了一个解决方案。东西现在很好用!
@Override
public void sendUserCreatedMail(CreateUserRequest createUserRequest) throws MessagingException, IOException {
//Get JavaMailSender
JavaMailSenderImpl mailSenderImpl = mailMapper.mapMailSender();
//Create email instance & send mail
MimeMessage mimeMessage = mailMapper.mapCreateUserRequestToMimeMessage(createUserRequest, mailSenderImpl.createMimeMessage());
mailSenderImpl.send(mimeMessage);
}
public MimeMessage mapCreateUserRequestToMimeMessage(CreateUserRequest createUserRequest, MimeMessage mimeMessage) throws MessagingException, IOException {
//set meta data using "MimeMessageHelper"
MimeMessageHelper helper = getMessageHelper(mimeMessage, createUserRequest.getEmail(),"Uw Real Estate Academy Account", "Real Estate Academy <" + this.emailConfiguration.getUsernameInfo()+">");
String htmlMessage = buildCreateUserRequestHtmlDocument("html/newUser.html", createUserRequest);
InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("images/rea-logo-rond.png");
helper.setText(htmlMessage, true);
helper.addInline("logo", new ByteArrayResource(IOUtils.toByteArray(inputStream)), "image/png");
return mimeMessage;
}
public String buildCreateUserRequestHtmlDocument(String filePath, CreateUserRequest createUserRequest) throws IOException {
InputStream inputStream = Main.class.getClassLoader().getResourceAsStream(filePath);
Document doc = Jsoup.parse(inputStream, "UTF-8", "https://www.realestateacademy.be");
Element loginElement = doc.getElementById("login");
Element passwordElement = doc.getElementById("password");
loginElement.text("Login: " + createUserRequest.getEmail());
passwordElement.text("Password: " + createUserRequest.getPassword());
return doc.toString();
}
推荐阅读
- c# - 如何将项目添加到 IEnumerable 中填充的对象的类列表中
- android - 如何让 Android 知道文件系统中手动添加的文件夹
- domain-driven-design - CQRS+DDD 命令端通过 id 查询其他聚合根
- javascript - JAVASCRIPT 从数组中删除父键
- python-3.x - 如何使用 YouTube Data API v3 通过搜索端点而不是视频端点来搜索视频时长?
- mysql - 如何解决每个派生表都必须有自己的别名?
- angular - 为什么要在 Angular 中设置依赖项提供程序?
- java - 我在我的 android 应用程序中遇到地理定位问题
- python - 在控制台中执行时python纸浆脚本错误
- jquery - 在不重新加载页面的情况下聆听另一个用户帐户上一个用户的更改的最佳方法?