Spring Boot Jar部署后静态文件无法访问的问题求助
解决方案
1. 替换只读的Jar内部存储目录
Spring Boot打包成Jar后,src/main/resources属于Jar包内部的只读目录,无法正常写入和访问外部请求。必须改用独立于Jar包的外部目录存储文件:
修改文件存储路径逻辑
推荐通过Spring配置注入灵活定义存储目录,替代硬编码的路径:
@Component public class FilesHelper { // 从配置文件读取存储目录,默认使用用户目录下的专属文件夹 @Value("${file.upload.dir:${user.home}/kanchanjunga-uploads}") private String uploadDir; public String saveFile(MultipartFile file) throws IOException { // 生成唯一文件名逻辑不变 UID uid = new UID(); String uidString = uid.toString().replace(':', '_'); String originalFilename = file.getOriginalFilename(); String extension = ""; if (originalFilename != null) { int dotIndex = originalFilename.lastIndexOf('.'); if (dotIndex >= 0) { extension = originalFilename.substring(dotIndex); originalFilename = originalFilename.substring(0, dotIndex); } } String filename = originalFilename + "_" + uidString + extension; // 使用外部存储目录 Path paths = Paths.get(uploadDir); if (!Files.exists(paths)) { Files.createDirectories(paths); } Path imagePath = paths.resolve(filename); try (InputStream inputStream = file.getInputStream()) { Files.copy(inputStream, imagePath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { throw new RuntimeException("Fail to save file " + filename, e); } // 后续要配合静态资源映射,路径改为/uploads/前缀 return KanchanjungaApplication.getServerUrl() + "/uploads/" + filename; } public Boolean deleteExistingFile(String fileName) { String filePathString = fileName.replace(KanchanjungaApplication.getServerUrl() + "/uploads/", ""); Path filePath = Paths.get(uploadDir, filePathString); try { Files.deleteIfExists(filePath); return true; } catch (IOException e) { e.printStackTrace(); } return false; } }
2. 配置静态资源映射
要让外部目录的文件能通过HTTP访问,需添加Spring MVC静态资源映射配置:
@Configuration public class WebConfig implements WebMvcConfigurer { @Value("${file.upload.dir:${user.home}/kanchanjunga-uploads}") private String uploadDir; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 映射 /uploads/** 请求到外部存储目录 registry.addResourceHandler("/uploads/**") .addResourceLocations("file:" + uploadDir + "/"); } }
3. 动态获取服务地址,移除硬编码
硬编码localhost:9000无法适配云端部署,改为通过配置注入动态地址:
@Component public class KanchanjungaApplication implements CommandLineRunner { @Value("${server.url:http://localhost:9000}") private String serverUrl; // 提供静态方法供FilesHelper调用 public static String getServerUrl() { return serverUrl; } // 原有CommandLineRunner逻辑不变 @Override public void run(String... args) throws Exception { // ... } }
4. 云端部署适配
云端部署时,只需在application.properties或application.yml中修改配置:
# 容器部署时可设置为容器内目录,配合卷挂载持久化 file.upload.dir=/app/kanchanjunga-uploads # 云端服务的公网域名或负载均衡地址 server.url=https://your-cloud-domain.com
如果用Docker部署,需配置卷挂载将容器内的/app/kanchanjunga-uploads映射到宿主机或云存储服务,避免容器重启后文件丢失。
内容的提问来源于stack exchange,提问作者nirah tmg
相关产品推荐
相关产品推荐

