Java从数据库中读取Blob图片并显示的方法

季宁
季宁
发布时间:2026-10-14 | 6人浏览过
原创

在Java Web开发中,将图片以BLOB(Binary Large Object)形式存储在数据库中是常见需求。本文将演示如何通过JDBC驱动连接Oracle和MySQL数据库,读取二进制流数据,并在Servlet中将其转换为JPEG格式输出至JSP页面,支持图片缩放功能。

第一种方案:直接流式输出

该方法的核心是将数据库中的Blob字段转换为输入流,通过Response的OutputStream直接写入客户端浏览器。此方式适用于不需要在前端对图片进行处理或缩放的场景。

第1步:建立数据库连接并获取输入流

首先,使用JDBC获取连接,执行查询语句提取Blob列的二进制流。关键操作包括:
- 调用 PreparedStatement.executeQuery() 获取结果集。
- 使用 rs.getBinaryStream(1) 获取Blob对应的InputStream。

Connection conn = DBManager.getConnection();
String sql = "SELECT picture FROM teacher WHERE id=1";
PreparedStatement ps = null;
ResultSet rs = null;
InputStream is = null;
OutputStream os = null;
try {
    ps = conn.prepareStatement(sql);
    rs = ps.executeQuery();
    if(rs.next()){
        is = rs.getBinaryStream(1); // 获取图片二进制流
    }
    // ... 后续输出逻辑
}

第2步:配置响应头并写入输出流

设置Servlet或页面的Content-Type为 text/html 或具体的图片类型,获取 response.getOutputStream(),循环读取输入流数据并写入输出流。务必在 finally 块中关闭所有资源以防内存泄漏。

response.setContentType("text/html"); // 实际应用中建议设为 image/jpeg
os = response.getOutputStream();
byte buf[] = new byte[1024];
int num;
while((num=is.read(buf))!=-1){
    os.write(buf, 0, num);
}
// 关闭资源的代码略

第3步:在JSP页面上引用

在HTML中使用 <img> 标签,src属性指向处理图片的Servlet地址。

复制代码 代码如下:
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <img name="pic" src="<%=basePath+"servlet/DownloadAsStream"%>"/>

第二种方案:带缩放的完整流程(针对Oracle)

当需要统一图片尺寸时,需先将BLOB转为字节数组,利用Java AWT进行缩放,再转回字节输出。以下示例基于Oracle数据库。

第1步:配置数据库连接参数

创建一个工具类 OracleQueryBean,负责加载Oracle JDBC驱动并建立连接。连接信息建议从配置文件读取以提高灵活性。

public Connection getConnection(){
    GetPara oGetPara = new GetPara();
    String strIP = oGetPara.getPara("serverip");
    String strPort = oGetPara.getPara("port");
    String strDBName = oGetPara.getPara("dbname");
    String strUser = oGetPara.getPara("user");
    String strPassword = oGetPara.getPara("password");
    String oracleUrlToConnect = "jdbc:oracle:thin:@"+strIP+":"+strPort+":"+strDBName;
    this.myConnection = DriverManager.getConnection(oracleUrlToConnect, strUser, strPassword);
    return this.myConnection;
}

第2步:读取Blob字段并转换为字节数组

在 GetImgByteById 方法中,执行SQL查询获取Blob对象,调用 blob.getBinaryStream() 读取数据。注意处理大文件时的长度转换。

java.sql.Blob blob = myResultSet.getBlob(this.strImgName);
InputStream inStream = blob.getBinaryStream();
long nLen = blob.length();
int nSize = (int) nLen;
data = new byte[nSize];
inStream.read(data); // 注意实际使用中可能需要循环读取以保证完整性
inStream.close();

第3步:实现图片缩放功能

使用 javax.imageio.ImageIO 和 java.awt.geom.AffineTransform 对图像进行等比或非等比缩放。创建指定宽高的BufferedImage,将原始图像绘制其中,最后写回字节数组。

private byte[] ChangeImgSize(byte[] data, int nw, int nh){
    BufferedImage bis = ImageIO.read(new ByteArrayInputStream(data));
    double sx = (double) nw / bis.getWidth();
    double sy = (double) nh / bis.getHeight();
    AffineTransform transform = new AffineTransform();
    transform.setToScale(sx, sy);
    AffineTransformOp ato = new AffineTransformOp(transform, null);
    BufferedImage bid = new BufferedImage(nw, nh, BufferedImage.TYPE_3BYTE_BGR);
    ato.filter(bis, bid);
    
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(bid, "jpeg", baos); // 也可根据原图格式选择 png 等
    return baos.toByteArray();
}

第4步:在JSP中展示并处理请求

JSP页面接收ID及宽高参数,实例化Bean获取处理后的字节数组,设置响应类型为 image/jpeg 并写出。最后需清除JSP隐含的输出缓冲区。

复制代码 代码如下:
<%@ page language="java" contentType="text/html;;charset=gbk" %> <jsp:useBean id="OrcleQuery" scope="page" class="HLFtiDemo.OracleQueryBean" /> <% response.setContentType("image/jpeg"); String strID = request.getParameter("id"); String strWidth = request.getParameter("w"); String strHeight = request.getParameter("h"); byte[] data = null; if(strID != null){ int nWith = Integer.parseInt(strWidth); int nHeight = Integer.parseInt(strHeight); data = OrcleQuery.GetImgByteById(strID, nWith, nHeight); ServletOutputStream op = response.getOutputStream(); op.write(data, 0, data.length); op.flush(); out.clear(); out = pageContext.pushBody(); } %>

第三种方案:MySQL环境下的Servlet实现

对于MySQL数据库,操作流程类似,主要区别在于Driver类和URL格式。此处提供一个完整的Servlet类 ReadPhoto 示例。

第1步:Servlet核心逻辑

在 doGet 中,获取图片ID,查询数据库获得Blob流。为了确保兼容性,可以将读取到的 BufferedImage 重新编码为JPEG格式输出。

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String idParam = request.getParameter("id");
    if(idParam == null) return;
    response.setContentType("image/jpeg");
    try {
        InputStream is = query_getPhotoImageBlob(Integer.parseInt(idParam));
        if(is != null){
            is = new BufferedInputStream(is);
            BufferedImage bi = ImageIO.read(is);
            OutputStream os = response.getOutputStream();
            // 使用JPEG编码器重新输出,确保格式统一
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
            encoder.encode(bi);
            os.flush();
            os.close();
        }
    } catch(Exception e) { e.printStackTrace(); }
}

第2步:数据库查询辅助方法

封装一个静态方法用于执行MySQL查询,返回图片的InputStream。注意处理资源释放。

public static InputStream query_getPhotoImageBlob(int id) throws SQLException {
    String sql = "select photo from photo where id=?";
    Connection con = DriverManager.getConnection(...);
    PreparedStatement pstmt = con.prepareStatement(sql);
    pstmt.setInt(1, id);
    ResultSet rs = pstmt.executeQuery();
    InputStream result = null;
    if(rs.next()){ result = rs.getBlob("photo").getBinaryStream(); }
    // 关闭资源...
    return result;
}

第3步:注册Servlet映射

在 web.xml 中配置该Servlet,定义URL Pattern以便前端访问。

复制代码 代码如下:
<servlet> <servlet-name>genImage</servlet-name> <servlet-class>ReadPhoto</servlet-class> </servlet> <servlet-mapping> <servlet-name>genImage</servlet-name> <url-pattern>/genImage</url-pattern> </servlet-mapping>

第4步:前端JSP调用

通过 <img> 标签指向配置的Servlet路径,并传入图片ID作为参数。

复制代码 代码如下:
<img style="width:320px;height:240px" src="<%=basePath%>/genImage?id=3"/>

以上就是Java从数据库中读取Blob对象图片并显示的详细内容,更多关于Java数据库交互的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表