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

Spring Boot+Thymeleaf随机文档图片错误显示问题求助

解决随机文档无图片字段却显示图片的问题

问题场景

数据库集合包含两个文档:

  • doc1
    id: 1
    title: "example"
    image: "binary numbers..."
    
  • doc2
    id: 2
    title: "example2"
    

当前API逻辑(用于返回随机文档):

@GetMapping("/getRandomSummerCamps")
public String getRandomSummerCamps(Model model) {
    countSummerCamps.incrementAndGet();
    if (getCountSummerCamps() <= adventureHolidaysService.countAdventureHolidays("summerCamps")) {
        AdventureHolidays photo = adventureHolidaysService.getPhoto();
        model.addAttribute("randomSummerCamps", adventureHolidaysService.findRandomAdventureHolidays("summerCamps"));
        System.out.println("in if");
        model.addAttribute("randomImage", Base64.getEncoder().encodeToString(photo.getImage().getData()));
        return "randomSummerCamps";
    } else {
        countSummerCamps.set(0);
        return "noMoreDoc";
    }
}

前端HTML代码:

<tr th:each="randomSummerCamps:${randomSummerCamps}">
<div class="title">
    <h1>We think this trip best suit you.</h1>
    <h1 th:text="${randomSummerCamps.title}"></h1>
    <h1 th:text="${randomSummerCamps.state}"></h1>
    <div class="description">
        <td th:text="${randomSummerCamps.description}"></td>
    </div>
    <img alt="sample" th:src="*{'data:image/png;base64,'+image}" src=""/>
    <button type="button" onclick="document.location.href = '/adventureHolidays/getRandomSummerCamps'">Randomize
        again!
    </button>
</div>

问题现象

仅doc1存在图片字段,但两个文档均显示图片;标题、状态等字段显示正常,无图片字段的doc2错误渲染了图片。

问题根源

  1. API逻辑不关联:randomImage是通过单独的getPhoto()获取的,和当前随机返回的randomSummerCamps文档没有绑定关系,无论随机到哪个文档,都会传递同一个图片数据到前端。
  2. 前端无判断逻辑:HTML中未检查当前文档是否存在图片字段,直接渲染img标签,导致无图片的文档也会显示默认/之前的图片。

解决方案

方案1:绑定随机文档与图片数据(推荐)

修改API,直接从随机返回的文档中处理图片,确保图片数据与当前文档关联:

@GetMapping("/getRandomSummerCamps")
public String getRandomSummerCamps(Model model) {
    countSummerCamps.incrementAndGet();
    int totalDocs = adventureHolidaysService.countAdventureHolidays("summerCamps");
    
    if (getCountSummerCamps() <= totalDocs) {
        // 获取随机文档
        AdventureHolidays randomCamp = adventureHolidaysService.findRandomAdventureHolidays("summerCamps");
        model.addAttribute("randomSummerCamps", randomCamp);
        
        // 仅当文档存在图片时,生成Base64编码
        if (randomCamp.getImage() != null && randomCamp.getImage().getData() != null) {
            String base64Image = Base64.getEncoder().encodeToString(randomCamp.getImage().getData());
            model.addAttribute("randomImage", base64Image);
        } else {
            model.addAttribute("randomImage", null);
        }
        
        System.out.println("in if");
        return "randomSummerCamps";
    } else {
        countSummerCamps.set(0);
        return "noMoreDoc";
    }
}

同时修改HTML,添加图片存在性判断:

<tr th:each="randomSummerCamps:${randomSummerCamps}">
<div class="title">
    <h1>We think this trip best suit you.</h1>
    <h1 th:text="${randomSummerCamps.title}"></h1>
    <h1 th:text="${randomSummerCamps.state}"></h1>
    <div class="description">
        <td th:text="${randomSummerCamps.description}"></td>
    </div>
    <!-- 仅当randomImage不为空时渲染图片 -->
    <img th:if="${randomImage != null}" alt="sample" th:src="*{data:image/png;base64,${randomImage}}" src=""/>
    <button type="button" onclick="document.location.href = '/adventureHolidays/getRandomSummerCamps'">Randomize
        again!
    </button>
</div>

如果findRandomAdventureHolidays返回的是文档集合,可在实体类中新增base64Image字段,遍历集合时为每个文档处理图片:

// 在AdventureHolidays实体类中添加字段
private String base64Image;

// API中修改处理逻辑
List<AdventureHolidays> randomCamps = adventureHolidaysService.findRandomAdventureHolidays("summerCamps");
for (AdventureHolidays camp : randomCamps) {
    if (camp.getImage() != null && camp.getImage().getData() != null) {
        camp.setBase64Image(Base64.getEncoder().encodeToString(camp.getImage().getData()));
    }
}
model.addAttribute("randomSummerCamps", randomCamps);

对应HTML调整为:

<img th:if="${randomSummerCamps.base64Image != null}" alt="sample" th:src="*{data:image/png;base64,${randomSummerCamps.base64Image}}" src=""/>

方案2:前端直接判断文档字段

若不想修改API,可在HTML中直接判断当前文档是否存在图片字段(需确保无图片时该字段为null):

<img th:if="${randomSummerCamps.image != null}" alt="sample" th:src="*{data:image/png;base64,${#strings.base64Encode(randomSummerCamps.image.data)}}" src=""/>

注:此方式依赖Thymeleaf的#strings.base64Encode工具方法,需确保相关依赖配置正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 03:06:21