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

Spring Boot图片上传至指定路径报错,寻求技术解决方案

解决文件上传时的FileNotFoundException问题

问题根源

你遇到的FileNotFoundException核心原因是路径解析错误:硬编码的/uploads/profile-pictures/在Windows系统下被解析为磁盘根目录路径,但应用实际期望在Tomcat部署目录下创建该路径,导致目录不存在。此外代码里还有几个潜在bug会加剧问题:

  • 文件类型判断逻辑颠倒且匹配错误
  • 旧文件删除时的路径解析未关联真实部署目录
  • 未确保上传目录的创建权限

修复方案

1. 修正文件类型校验逻辑

原代码会误判合法图片为非法类型,改成正确的MIME类型校验:

assert contentType != null;
// 仅允许image/jpeg和image/png类型
if (!contentType.equals("image/jpeg") && !contentType.equals("image/png")) {
    throw new IllegalArgumentException("Invalid file type. Only jpeg and png are allowed");
}

2. 获取Web应用的真实上传目录

不能用硬编码的绝对路径开头字符串,需要通过ServletContext获取应用的真实部署路径(Spring环境下可直接注入):

@Autowired
private ServletContext servletContext;

// 去掉开头的/,使用相对路径
private static final String UPLOAD_DIR = "uploads/profile-pictures/";

@Override
public void uploadProfilePicture(User curUser, MultipartFile file){
    // ... 类型和大小校验 ...

    try {
        // 获取上传目录的真实物理路径
        String realBasePath = servletContext.getRealPath(UPLOAD_DIR);
        Path userUploadPath = Paths.get(realBasePath, curUser.getUsername());

        // 创建多级目录,同时确保权限
        if (!Files.exists(userUploadPath)) {
            Files.createDirectories(userUploadPath);
            // 赋予读写权限,避免Tomcat无权限操作
            userUploadPath.toFile().setWritable(true, false);
            userUploadPath.toFile().setReadable(true, false);
        }

3. 修正旧文件删除的路径解析

旧文件路径需要基于真实部署目录解析,而不是直接截取数据库字符串:

if (curUser.getProfilePicturePath() != null) {
    // 截取数据库中存储的相对路径部分
    String relativeOldPath = curUser.getProfilePicturePath().substring(1);
    Path oldFilePath = Paths.get(servletContext.getRealPath("/"), relativeOldPath);
    Files.deleteIfExists(oldFilePath);
}

4. 确保文件传输路径正确

后续的文件写入和数据库路径更新保持相对路径格式:

String fileExtension = contentType.equals("image/jpeg") ? "jpg" : "png";
fileName = curUser.getId() + "_" + UUID.randomUUID() + "." + fileExtension;

Path filePath = userUploadPath.resolve(fileName);
file.transferTo(filePath.toFile());

// 数据库存储相对路径,方便后续读取
curUser.setProfilePicturePath("/" + UPLOAD_DIR + curUser.getUsername() + "/" + fileName);
userRepository.save(curUser);

5. 增强异常排查信息

在catch块中添加详细错误日志,方便定位问题:

catch (IOException e) {
    // 建议使用SLF4J等日志框架输出详细栈信息
    System.err.println("Upload failed: " + e.getMessage());
    e.printStackTrace();
    throw new RuntimeException("Failed to upload profile picture", e);
}

额外建议

  • 不要依赖Tomcat的临时工作目录(错误日志中的路径属于临时目录,重启Tomcat会被清空),配置固定的上传目录,比如Spring Boot可在application.properties中设置:
    spring.servlet.multipart.location=/your/fixed/upload/directory
    
  • 确保Tomcat进程对上传目录有读写权限,Windows下可能需要手动给Tomcat服务账户赋权

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:55:21