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

Spring MVC如何展示多个从数据库读取后转Base64编码的图片

现有代码的问题

  • Iterable是一次性迭代对象,调用Iterables.size(postsMain)会遍历完整个集合,后续再调用iterator()获取到的迭代器已经没有元素了
  • 循环逻辑错误:每次循环都新建迭代器调用next(),永远只会拿到第一个帖子的图片,所有元素都是同一张图
  • 循环边界错误:count <= size会多循环一次,触发NoSuchElementException异常
  • 分开存储帖子列表和图片列表容易出现顺序不匹配的问题,后续维护难度高

正确实现方案(优先推荐)

直接给PostModel新增不映射数据库的临时字段存储对应图片的Base64编码,让每个帖子和自己的图片绑定,避免顺序错乱问题:

  1. 先修改PostModel实体类,新增临时字段
// 加在PostModel类中,@Transient注解表示该字段不参与数据库ORM映射
@Transient
private String base64Image;

// 补上该字段的getter、setter方法
public String getBase64Image() {
    return base64Image;
}
public void setBase64Image(String base64Image) {
    this.base64Image = base64Image;
}
  1. 修改控制器代码
@GetMapping("/")
public ModelAndView home (Model model) {
    ModelAndView modelAndView = new ModelAndView("home");
    Iterable<PostModel> postsMain = postRepository.findAll();
    // 把Iterable转成List方便遍历处理
    List<PostModel> postList = StreamSupport.stream(postsMain.spliterator(), false)
            .toList();
    // 遍历每个帖子,给对应图片转Base64后存入自身临时字段
    for (PostModel post : postList) {
        byte[] encodeBase64 = Base64.encodeBase64(post.getImage());
        String base64Encoded = new String(encodeBase64, StandardCharsets.UTF_8);
        post.setBase64Image(base64Encoded);
    }
    // 仅需要传递处理好的帖子列表即可
    modelAndView.addObject("posts_main", postList);
    return modelAndView;
}
  1. 前端Thymeleaf渲染代码
    直接遍历帖子列表,同时取出对应标题和图片即可:
<!-- 遍历所有帖子 -->
<div th:each="post : ${posts_main}" class="post-item">
  <h3 th:text="${post.title}">帖子标题</h3>
  <img class="post-image" th:src="@{'data:image/jpeg;base64,'+${post.base64Image}}">
</div>

不想修改实体类的替代方案

如果不希望改动PostModel,也可以保持两个列表传递,只要保证遍历顺序一致即可,控制器代码如下:

@GetMapping("/")
public ModelAndView home (Model model) {
    ModelAndView modelAndView = new ModelAndView("home");
    Iterable<PostModel> postsMain = postRepository.findAll();
    List<PostModel> postList = StreamSupport.stream(postsMain.spliterator(), false)
            .toList();
    List<String> contentImages = new ArrayList<>();
    for (PostModel post : postList) {
        byte[] encodeBase64 = Base64.encodeBase64(post.getImage());
        String base64Encoded = new String(encodeBase64, StandardCharsets.UTF_8);
        contentImages.add(base64Encoded);
    }
    modelAndView.addObject("contentImages", contentImages);
    modelAndView.addObject("posts_main", postList);
    return modelAndView;
}

前端通过索引匹配对应图片:

<div th:each="post, iterStat : ${posts_main}" class="post-item">
  <h3 th:text="${post.title}">帖子标题</h3>
  <img class="post-image" th:src="@{'data:image/jpeg;base64,'+${contentImages[iterStat.index]}}">
</div>

补充注意事项

  • 建议用StandardCharsets.UTF_8代替硬编码字符串"UTF-8",避免字符集不存在的异常
  • 如果图片格式不只有jpeg,建议把图片格式也存在PostModel字段中,动态拼接src前缀
  • 大图片转Base64会导致页面体积大幅增加、加载变慢,流量消耗高,数据量大的场景建议改成单独的图片接口返回二进制流,前端用URL访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:15:04