【问题标题】:Display BLOB (image) through JSP通过 JSP 显示 BLOB(图像)
【发布时间】:2025-12-15 18:55:01
【问题描述】:

我有一个显示员工图表的代码。

数据(姓名、电话、照片等)存储在 SQLServer 中并通过 JSP 显示。 显示数据没问题,除了图片 .jpg(存储在 IMAGE=BLOB 列中)。

顺便说一句,我已经显示了图像(参见下面的代码),但我不知道如何将它放在 .css 中定义的区域中(也参见下面的代码),因为图像在浏览器中通过resultSet加载整个页面。

有谁知道我如何“构图”图像?

<%
Connection con = FactoryConnection_SQL_SERVER.getConnection("empCHART");
Statement stSuper = con.createStatement();
Statement stSetor = con.createStatement();

Blob image = null;
byte[] imgData = null;

ResultSet rsSuper = stSuper.executeQuery("SELECT * FROM funChart WHERE dept = 'myDept'");

if (rsSuper.next()) {
image = rsSuper.getBlob(12);
imgData = image.getBytes(1, (int) image.length());
response.setContentType("image/gif");
OutputStream o = response.getOutputStream();
//o.write(imgData); // even here we got the same as below.
//o.flush();
//o.close();

--[...]

<table style="margin: 0px; margin-top: 15px;">
<tr>
<td id="photo">
<img title="<%=rsSuper.getString("empName").trim()%>" src="<%= o.wite(imageData); o.flush(); o.close(); %>" />
</td>
</td>

<td id="empData">
<h3><%=rsSuper.getString("empName")%></h3>
<p><%=rsSuper.getString("Position")%></p>
<p>Id:<br/><%=rsSuper.getString("id")%></p>
<p>Phone:<br/><%=rsSuper.getString("Phone")%></p>
<p>E-Mail:<br/><%=rsSuper.getString("Email")%></p>
</td>
</table>

这里是用来构图的片段:

#photo
{
    padding: 0px;
    vertical-align: middle;
    text-align: center;
    width: 170px;
    height: 220px;
}

提前致谢!

【问题讨论】:

  • 标准解决方案是将 HTML(此处)与图像分开,通常由另一个响应浏览器请求的 servlet 提供服务。所以 JSP 页面只包含类似&lt;img src=myservlet?img=someId&gt; 的内容,并且您有一个 servlet,您可以在其中响应图像的二进制文件。另一种解决方案(我不推荐)是在 JSP 页面中以 base64 格式发送图像。

标签: java jakarta-ee


【解决方案1】:

你在这里犯了一些根本性的错误。 &lt;img src&gt; 必须指向一个 URL,不包含图像的二进制内容。 JSP 页面本身的内容类型不应设置为image/gif。它应该保持默认为text/html。正如您所期望的那样,网络服务器不应该在 HTML 结果中包含具体图像。网络浏览器根据src 属性中的 URL 单独下载图像,然后相应地呈现它们。

最简单的方法是创建一个单独的 servlet,将图像从 DB 流式传输到响应正文。您可以通过请求参数或路径信息来唯一标识图像。这是一个使用请求参数的示例:

<img src="imageServlet?id=<%=rsSuper.getString("id")%>" />

doGet() 方法应该基本上执行这项工作:

String id = request.getParameter("id");

// ...

InputStream input = resultSet.getBinaryStream("imageColumnName");
OutputStream output = response.getOutputStream();
response.setContentType("image/gif");
// Now write input to output the usual way.

与具体问题无关,十年来官方强烈反对以这种方式使用 scriptlets。也许您正在阅读完全过时的书籍/教程,或者正在维护一个古老的 JSP Web 应用程序。有关一些见解,另请参阅以下问题的答案以获得一些提示:

【讨论】:

  • 或者,OP 可以覆盖 service() 方法,而不用担心 HTTP 方法。 :p
  • @Elite:如果客户端在语义上使用错误的方法来幂等地检索图像,这不是 servlet 的错。它总是得到。其他任何事情都是错误的。
  • @BalusC,确切地说。我见过大量滥用 Servlet 的行为。
  • @thinksteep:在网络浏览器中,是的。不在网络服务器中。我只是不明白你为什么问这个。你了解 HTML 的工作原理吗?
  • @thinksteep:是的,否则它将如何检索图像?在 Chrome/IE9/Firebug 中按 F12 并在“网络”选项卡中研究 HTTP 流量。
【解决方案2】:

如果要通过 HTML 标记显示图像,则必须将图像指向加载图像的服务器中的资源,以便客户端浏览器可以加载它。这样,您就可以设置&lt;img /&gt; 标签的样式。

为了做到这一点,大多数人写了一个ImageServlet来加载图像的二进制数据并写一个&lt;img src = "/source/to/someImageServlet?id=&lt;%=rsSuper.getString("id")%&gt;" id = "photo"/&gt;

【讨论】:

    【解决方案3】:
      Connection con = new DBConnection().getConnection();
            String sql = " SELECT * FROM tea ";
            PreparedStatement ps = con.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
    
            while (rs.next()) {
                byte[] imgData = rs.getBytes("img"); // blob field 
                request.setAttribute("rvi", "Ravinath");
                rs.getString("teatitle");
    
                String encode = Base64.getEncoder().encodeToString(imgData);
                request.setAttribute("imgBase", encode);
            }
    

    然后使用jstl提取jsp页面上的属性

     <img src="data:image/jpeg;base64,${imgBase}" />
    

    【讨论】:

    • 需要注意的是,这种方法效率极低。最多将其用作图像上传的预览功能。在精心设计的 Web 应用程序中,这些临时图像首先还没有存储在 DB 中。换句话说,这种方法绝对不推荐用于显示静态图像。
    【解决方案4】:
    //globle variable
    List listmap = new ArrayList();//with getter/setter
    
    //method
    Connection con = conn.getConnection();
    PreparedStatement ps = null;
    String query="select img from tablename";
    ps = con.prepareStatement(query);
    resultSet = ps.executeQuery();
    while (resultSet.next()) {
    PackagePojo p1=new PackagePojo();
    // pojo class with field private String imagePath with getter/setter;
    byte[] img = resultSet.getBytes("PTOIMAGE");//PTOIMAGE db column name
    String encode=Base64.encodeBase64String(img );
    p1.setImagePath(encode);
    listmap.add(p1);
    }
    
    //in jsp with struts2
    
    <s:iterator value="listmap">
    <img src="data:image/jpeg;base64,${imagePath}" alt="bhudutt" title="bhudutt" />
    </s:iterator>
    

    【讨论】:

    • user3773686,感谢您抽出宝贵时间,但不推荐您的解决方案,正如 BalusC 在 Ravinath 回答的解决方案(与您的解决方案非常相似)中评论的那样。