You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
        }
    });
}

问题原因

  1. 静态资源缓存机制:Spring MVC/Spring Boot启动时,会将/resources/static目录下的静态资源扫描并加载到内存映射中,运行时不会自动监听该目录的新增文件。上传的图片属于运行时新增资源,不在服务器的资源映射表中,因此返回404;重启Tomcat后,服务器重新扫描目录,新增图片被加入映射,即可正常访问。
  2. 类路径写入限制:/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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 02:51:09