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

如何将MySQL中的Blob转换并在JSP页面显示?Spring MVC场景

完善DAO代码(补全资源关闭逻辑)

首先先把你未完成的DAO代码补全,避免数据库连接泄漏:

public List<PhotoResponseDTO> getAllPhoto() throws IOException {
    List<PhotoResponseDTO> photos = new ArrayList<>(); 
    String sql = "SELECT * FROM photot";
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
        ps = con.prepareStatement(sql);
        rs = ps.executeQuery();
        
        while(rs.next()) {
            PhotoResponseDTO photo = new PhotoResponseDTO();
            photo.setId(rs.getInt("id"));
            photo.setImage(rs.getBytes("image")); // 将Blob转为字节数组
            photo.setDate(rs.getString("date"));
            photos.add(photo);
        }
    } catch (SQLException e) {
        e.printStackTrace();
        // 实际项目建议抛自定义业务异常或统一处理
    } finally {
        // 按顺序关闭资源,避免内存泄漏
        try {
            if (rs != null) rs.close();
            if (ps != null) ps.close();
            // 若con是局部变量需关闭,Spring连接池管理的连接无需手动关闭
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return photos;
}

两种在JSP显示Blob图片的方案

方案一:转Base64直接嵌入页面(适合小图片)

这种方式无需额外HTTP请求,直接把图片编码成字符串嵌入页面。

  1. Controller层处理编码
    在Controller中把图片字节数组转成Base64字符串,传递给JSP:
@Controller
@RequestMapping("/photos")
public class PhotoController {

    @Autowired
    private PhotoDAO photoDAO;

    @GetMapping("/list")
    public String getPhotoList(Model model) throws IOException {
        List<PhotoResponseDTO> photos = photoDAO.getAllPhoto();
        // 为每个图片生成Base64编码字符串
        for (PhotoResponseDTO photo : photos) {
            byte[] imageBytes = photo.getImage();
            if (imageBytes != null) {
                // 前缀需匹配图片类型,png则改为image/png
                String base64Image = "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(imageBytes);
                photo.setBase64Image(base64Image); // 需在DTO中新增base64Image字段及getter/setter
            }
        }
        model.addAttribute("photos", photos);
        return "photoList"; // 对应你的JSP文件名
    }
}

在PhotoResponseDTO中新增字段:

public class PhotoResponseDTO {
    private int id;
    private byte[] image;
    private String date;
    private String base64Image; // 新增字段

    // 原有getter/setter
    public String getBase64Image() { return base64Image; }
    public void setBase64Image(String base64Image) { this.base64Image = base64Image; }
}
  1. JSP页面渲染
    在photoList.jsp中遍历显示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>图片列表</title>
</head>
<body>
    <h1>图片列表</h1>
    <c:forEach items="${photos}" var="photo">
        <div>
            <p>上传日期:${photo.date}</p>
            <img src="${photo.base64Image}" alt="图片" width="200" height="200">
        </div>
        <hr>
    </c:forEach>
</body>
</html>

方案二:单独Controller输出图片流(适合大图片)

这种方式通过独立的接口返回图片流,更符合HTTP规范,避免页面加载过慢。

  1. 新增图片流接口
    在Controller中添加根据ID返回图片的方法,同时DAO新增单图查询逻辑:
@Controller
@RequestMapping("/photos")
public class PhotoController {

    @Autowired
    private PhotoDAO photoDAO;

    // 列表页跳转
    @GetMapping("/list")
    public String getPhotoList(Model model) throws IOException {
        List<PhotoResponseDTO> photos = photoDAO.getAllPhoto();
        model.addAttribute("photos", photos);
        return "photoList";
    }

    // 输出图片流
    @GetMapping("/image/{photoId}")
    public void getImage(@PathVariable("photoId") int photoId, HttpServletResponse response) throws IOException {
        PhotoResponseDTO photo = photoDAO.getPhotoById(photoId); // DAO需新增该方法
        if (photo != null && photo.getImage() != null) {
            byte[] imageBytes = photo.getImage();
            response.setContentType("image/jpeg"); // 匹配图片实际类型
            response.setHeader("Cache-Control", "max-age=3600"); // 可选缓存设置
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(imageBytes);
            outputStream.flush();
            outputStream.close();
        }
    }
}

DAO新增单图查询方法:

public PhotoResponseDTO getPhotoById(int photoId) throws SQLException {
    String sql = "SELECT * FROM photot WHERE id = ?";
    PreparedStatement ps = null;
    ResultSet rs = null;
    PhotoResponseDTO photo = null;
    try {
        ps = con.prepareStatement(sql);
        ps.setInt(1, photoId);
        rs = ps.executeQuery();
        if (rs.next()) {
            photo = new PhotoResponseDTO();
            photo.setId(rs.getInt("id"));
            photo.setImage(rs.getBytes("image"));
            photo.setDate(rs.getString("date"));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 关闭资源
        try {
            if (rs != null) rs.close();
            if (ps != null) ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return photo;
}
  1. JSP页面渲染
    通过img标签指向图片流接口:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>图片列表</title>
</head>
<body>
    <h1>图片列表</h1>
    <c:forEach items="${photos}" var="photo">
        <div>
            <p>上传日期:${photo.date}</p>
            <img src="${pageContext.request.contextPath}/photos/image/${photo.id}" alt="图片" width="200" height="200">
        </div>
        <hr>
    </c:forEach>
</body>
</html>

注意事项

  • 图片类型:若数据库存储的是png/gif等格式,需对应调整Content-Type和Base64前缀。
  • 异常处理:实际项目中不要直接打印StackTrace,建议统一捕获异常并跳转错误页面。
  • 框架整合:后续可以学习Spring JdbcTemplate或MyBatis,它们会自动管理数据库连接,比原生JDBC更简洁安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:33:16