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

Spring Boot 3.1.2升级后旧版Windows Server无法删除临时文件

问题描述

升级Spring Boot至3.1.2版本并切换到JDK17后,在低于Windows Server 2022的服务器上运行应用时,文件上传出现临时文件无法删除的错误,报错信息如下:

ERROR 07.04.24 06:49:59,284 [https-jsse-nio-8585-exec-3] Http11Processor           Error processing request
java.io.UncheckedIOException: Cannot delete C:\Users\test\AppData\Local\Temp\tomcat.8585.7214288071310798307\work\Tomcat\localhost\ROOT\upload_80353576_cb85_40bc_938c_3088b7428c44_00142374.tmp
    at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.delete(DiskFileItem.java:429) ~[test.jar:?]
    ...
Caused by: java.io.IOException: Cannot delete C:\Users\test\AppData\Local\Temp\tomcat.8585.7214288071310798307\work\Tomcat\localhost\ROOT\upload_80353576_cb85_40bc_938c_3088b7428c44_00142374.tmp
    ... 13 more

Windows 10及Windows Server 2022环境下无此问题。

解决方案
  • 显式关闭文件输入流
    处理MultipartFile时,确保文件输入流被正确关闭,避免旧Windows系统锁定文件。推荐使用try-with-resources语法自动管理流:

    try (InputStream inputStream = multipartFile.getInputStream()) {
        // 处理文件逻辑
    } catch (IOException e) {
        // 异常处理
    }
    

    若未使用try-with-resources,需在处理完成后手动调用inputStream.close()。

  • 配置自定义临时文件目录
    避开系统默认的Temp目录,指定应用专属的临时目录,降低权限冲突概率。在application.properties中添加以下配置:

    # 自定义Spring Boot Multipart临时目录
    spring.servlet.multipart.location=./app-multipart-temp
    # 自定义Tomcat基础目录(包含临时文件)
    server.tomcat.basedir=./tomcat-base-temp
    # 确保请求结束后清理临时文件(默认已开启,显式声明更稳妥)
    spring.servlet.multipart.cleanup-after-request=true
    

    需保证应用对该目录有读写权限。

  • 添加JVM启动参数
    JDK17在旧Windows系统上的文件处理逻辑可能存在兼容性问题,添加以下参数禁用Alternate Data Streams(ADS):

    -Djdk.io.File.enableADS=false
    
  • 调整Tomcat版本
    Spring Boot 3.1.2默认绑定Tomcat 10.1.x,部分版本在旧Windows上存在临时文件删除bug。可尝试升级Tomcat至10.1.15+(该版本修复了部分Windows文件锁定问题),或在pom.xml中指定兼容版本:

    <properties>
        <tomcat.version>10.1.15</tomcat.version>
    </properties>
    
  • 手动触发临时文件删除
    若以上方案无效,可在请求处理完成后,手动获取临时文件路径并删除:

    // 获取MultipartFile对应的临时文件
    File tempFile = ((DiskFileItem) ((StandardMultipartHttpServletRequest) request).getFile("file").getStorageDescriptor()).getStoreLocation();
    // 在请求结束后异步删除
    new Thread(() -> {
        try {
            Thread.sleep(1000); // 延迟删除,确保文件已释放
            Files.delete(tempFile.toPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
    

    注意:需处理删除失败的异常,避免日志污染。

内容的提问来源于stack exchange,提问作者Gowri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:39:51