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

Spring Boot中已存储的用户图片无法显示的问题求助

问题描述

在Spring Boot项目中实现了Personne实体及关联图片的存储功能,图片已成功保存到/user-photos/对应ID目录下,数据库也存储了图片文件名,但Thymeleaf前端页面无法正常显示图片。相关代码如下:

Personne实体类代码

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Personne {
    
    @Id
    @GeneratedValue()
    private int id;
    @Column(length = 20 , nullable = false )
    private String frist_Name;
    @Column(length = 20 , nullable = false )
    private String last_Name;
    @Column(length = 10 , nullable = false , unique = true )
    private String cni;
    private String car_plate;
    private String Adress;
    @Column(length = 45 , nullable = true)
    private String image;
    
    @Transient
    public String getImagePath() {
        if (image == null || id == 0) return null;
        
        return "/user-photos/"+ id + "/" + image;
    }
}

控制器savePersonne方法代码

@PostMapping("/Personnes/save")
public String savePersonne(Personne personne, @RequestParam("file") MultipartFile file) throws IOException {
    
    String fileName = StringUtils.cleanPath(file.getOriginalFilename());
    personne.setImage(fileName);
    
    Personne savedPerso = repo.save(personne);
    
    String uploadDir = "./user-photos/" + savedPerso.getId();
    
    FileUploadUtil.saveFile(uploadDir, fileName, file);
    
    return "redirect:/personnes";   
}

saveFile工具方法代码

public static void saveFile(String uploadDir, String fileName,
            MultipartFile multipartFile) throws IOException {
        Path uploadPath = Paths.get(uploadDir);
         
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath);
        }
         
        try (InputStream inputStream = multipartFile.getInputStream()) {
            Path filePath = uploadPath.resolve(fileName);
            System.out.println(filePath.toFile().getAbsolutePath());
            Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException ioe) {        
            throw new IOException("Could not save image file: " + fileName, ioe);
        }      
}

Thymeleaf前端视图代码

<tbody>
    <th:block th:each="personne : ${listPersonnes}">
        <tr>
            <td><img th:src="@{${personne.imagePath}}" style="width: 100px;height: 100px"></td>
            <td>[[${personne.frist_Name}]]</td>
            <td>[[${personne.last_Name}]]</td>
            <td>[[${personne.adress}]]</td>
            <td>[[${personne.cni}]]</td>
            <td>[[${personne.car_plate}]]</td>
            
            <td>
            <a th:href="@{'/personnes/edit/' + ${personne.id}}">Edit</a>
            &nbsp;
            <a th:href="@{'/personnes/delete/' + ${personne.id}}">Delete</a>
            </td>
            
        </tr>
    </th:block>
</tbody>    
原因排查及解决办法

核心原因

Spring Boot默认不会对外暴露项目根目录下的./user-photos文件夹,前端请求图片时服务器无法找到对应资源,导致404错误。同时存在几个细节问题可能影响显示效果。

具体解决步骤

  1. 配置静态资源映射
    创建WebMvc配置类,将/user-photos/**路径映射到本地./user-photos目录,让Spring Boot能处理该目录下的资源请求:

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/user-photos/**")
                    .addResourceLocations("file:./user-photos/");
        }
    }
    
  2. 统一字段与路径大小写

    • 实体类中Adress字段首字母大写,但前端使用[[${personne.adress}]](小写a),建议将实体类的Adress改为adress,保持字段名与模板调用一致,避免潜在的属性访问问题。
    • 控制器请求路径/Personnes/save与其他请求/personnes大小写不一致,统一改为小写风格(如/personnes/save),避免路径匹配的隐性问题。
  3. 验证图片路径与资源可访问性

    • 打开浏览器开发者工具,查看图片标签的src属性是否生成正确路径(如/user-photos/1/test.jpg)。
    • 直接在浏览器地址栏访问该路径,确认是否能返回图片:若返回404,说明静态资源映射未配置生效;若返回图片,再检查模板渲染逻辑。
  4. 确认文件存储路径的正确性
    ./user-photos是相对于项目启动目录的路径:IDE启动时路径为项目根目录;jar包运行时路径为jar所在目录。可通过System.getProperty("user.dir")打印当前工作目录,确认图片是否存储在对应位置。

  5. 处理特殊文件名问题
    若文件名包含特殊字符或中文,可能导致路径解析错误。建议保存时生成唯一文件名(如UUID+原扩展名),避免冲突:

    String fileExtension = StringUtils.getFilenameExtension(file.getOriginalFilename());
    String fileName = UUID.randomUUID().toString() + "." + fileExtension;
    

内容的提问来源于stack exchange,提问作者el idrissi oussama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:40:25