Spring Boot Tomcat图片上传后404求助:重启后可正常显示
问题:上传头像后刷新页面返回404,重启Tomcat后恢复正常
我正在开发论坛项目,需要在用户页面展示头像。遇到的问题:将图片上传至磁盘后刷新页面,浏览器返回404错误:GET http://localhost:8080/images/1606504376_preview_wonder-day-among-us-21.png 404。图片确实存储在/resources/static/images目录,但无法被访问;重启Tomcat服务器后,图片可正常显示。请帮忙排查原因。
相关代码
展示用户视图页面的Controller方法
@GetMapping("/view") public String getViewPage(Model model, Principal principal) { User user = userService.findByUsername(principal.getName()); model.addAttribute("user", user); return "viewPage"; }
图片上传的Rest Controller方法
@PostMapping("/uploadImage") public ResponseEntity<Void> uploadImage(@RequestParam("file") MultipartFile file, Principal principal) throws IOException { User user = userService.findByUsername(principal.getName()); imageService.upload(file, user); return new ResponseEntity<>(HttpStatus.OK); }
用户视图页面代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户页面</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script type="text/javascript" src="js/uploadFile.js"></script> </head> <body> <table th:border="10" th:width="500" th:height="300" th:align="center"> <tr> <td>邮箱/登录名</td> </tr> <tr> <td>显示昵称</td> </tr> <tr> <td>头像</td> </tr> </table> <table th:border="10" th:width="500" th:height="300" th:align="center"> <tr> <td th:text="${user.getEmail()}">邮箱示例</td> </tr> <tr> <td th:text="${user.getUsernameForOtherUsers()}">显示昵称示例</td> </tr> <tr> <td> <img th:src="@{${user?.getImage()?.getShortPath()} + ${user?.getImage()?.getName()}}" alt=""> </td> </tr> </table> <form method="POST" enctype="multipart/form-data" id="fileUploadForm"> <label path="file">选择要上传的文件</label> <input type="file" name="file" /> <input type="submit" value="提交" id="submitButton"/> </form> </body> </html>
图片上传的JQuery脚本
$(document).ready(function() { $("#submitButton").click(function(event) { // 阻止表单默认提交行为 event.preventDefault(); // 调用Ajax提交 ajaxSubmitForm(); }); }); function ajaxSubmitForm() { // 获取表单对象 var form = $('#fileUploadForm')[0]; var data = new FormData(form); $("#submitButton").prop("disabled", true); $.ajax({ type: "POST", enctype: 'multipart/form-data', url: "/uploadImage", data: data, // 阻止jQuery自动将数据转为查询字符串 processData: false, contentType: false, cache: false, timeout: 1000000, success: function(data, textStatus, jqXHR) { $("#result").html(data); console.log("成功 : ", data); $("#submitButton").prop("disabled", false); $('#fileUploadForm')[0].reset(); }, error: function(jqXHR, textStatus, errorThrown) { $("#result").html(jqXHR.responseText); console.log("错误 : ", jqXHR.responseText); $("#submitButton").prop("disabled", false); } }); }
问题原因
- 静态资源缓存机制:Spring MVC/Spring Boot启动时,会将
/resources/static目录下的静态资源扫描并加载到内存映射中,运行时不会自动监听该目录的新增文件。上传的图片属于运行时新增资源,不在服务器的资源映射表中,因此返回404;重启Tomcat后,服务器重新扫描目录,新增图片被加入映射,即可正常访问。 - 类路径写入限制:
/resources/static属于项目类路径目录,生产环境打包成JAR/WAR后,无法直接向JAR内部写入文件,该上传方式在生产环境会直接失效。
解决方案
方案1:配置外部静态资源目录(推荐)
将上传目录改为磁盘外部路径,通过Spring配置映射为静态资源访问路径,既解决实时访问问题,也适配生产环境。
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 映射外部目录(示例:D:/forum_images/)到/images/**访问路径 registry.addResourceHandler("/images/**") .addResourceLocations("file:D:/forum_images/") .setCachePeriod(0); // 关闭缓存,确保新增文件实时可访问 } }
同时修改imageService.upload方法,将图片保存到上述外部目录,而非/resources/static/images。
方案2:开发环境临时禁用缓存
仅适合开发测试,在application.properties中添加:
spring.web.resources.cache.period=0 spring.web.resources.chain.cache=false
该方式会降低生产环境性能,不建议线上使用。
内容的提问来源于stack exchange,提问作者rickandmorty
相关产品推荐
相关产品推荐

