SpringBoot应用Docker化部署K8s后无法读取Resources目录图片资源
问题根因
本地Eclipse运行时,项目资源直接以文件形式存在磁盘目录中,ResourceUtils.getFile() 可以直接获取真实文件路径;但应用打包为Spring Boot可执行jar、部署到K8s容器后,资源被打包在jar包的嵌套结构内,不存在独立的磁盘文件路径,ResourceUtils.getFile() 无法解析jar内部资源的绝对路径,因此抛出文件不存在的异常。
额外说明:ResourceUtils.getFile() 本身设计就不支持读取jar包内的classpath资源,仅能读取文件系统上的真实文件,生产打包部署场景禁止用该方法读取内置资源。另外你代码里写的src/main/resources/前缀路径本身就是错误的:打包后该源码目录不会存在于构建产物中,本地能跑只是因为IDE运行时直接读取了工作区的源码文件,属于偶发的环境兼容问题。
修复步骤
直接通过classpath读取资源输入流构造邮件内联图片数据源,不需要将资源解析为磁盘文件,修改读取图片的代码段即可:
- 移除原有错误的
FileDataSource+ResourceUtils.getFile()逻辑 - 用Spring提供的
ClassPathResource加载classpath下的图片资源,通过输入流构造ByteArrayDataSource
修改后的对应代码如下:
MimeBodyPart messageBodyPart2 = new MimeBodyPart(); // 直接加载classpath下的图片资源,路径不需要加src/main/resources前缀 ClassPathResource emailImgResource = new ClassPathResource("External_Files/email_template.png"); // 基于资源输入流构造数据源,指定正确的MIME类型 DataSource fds = new ByteArrayDataSource(emailImgResource.getInputStream(), "image/png"); messageBodyPart2.setDataHandler(new DataHandler(fds)); messageBodyPart2.setHeader(AppConstants.CONTENT_ID, AppConstants.IMAGE_HEADER); multipart.addBodyPart(messageBodyPart2);
注意事项
- 导入
ByteArrayDataSource时注意匹配你用的Mail包版本:Spring Boot 2.x使用javax包,导入路径为javax.mail.util.ByteArrayDataSource;Spring Boot 3.x使用Jakarta包,导入路径为jakarta.mail.util.ByteArrayDataSource - 该实现直接读取jar包内的资源流,不需要额外解压文件,兼容本地IDE运行、独立jar运行、容器化部署等所有场景
- 确认你的png文件在构建时被正确打包到jar的
BOOT-INF/classes/External_Files/路径下,可通过jar tf app.jar | grep email_template.png命令验证打包结果
内容的提问来源于stack exchange,提问作者Indranil Halder
相关产品推荐
相关产品推荐

