如何从JSP页面中的数据库中检索和显示图像?

时间:2010-02-26 08:49:25

标签: java image jsp servlets

如何在JSP页面中检索和显示数据库中的图像?

5 个答案:

答案 0 :(得分:64)

让我们分步看看会发生什么:

  • JSP基本上是一种应该生成HTML输出的视图技术。
  • 要以HTML格式显示图片,您需要HTML <img>元素。
  • 要让它找到图像,您需要指定其src属性。
  • src属性需要指向有效的http:// URL,因此不是本地磁盘文件系统路径file://,因为当服务器和客户端在物理上不同的情况下运行时,它永远不会工作机器。
  • 图片网址需要在请求路径(例如http://example.com/context/images/foo.png)或请求参数(例如http://example.com/context/images?id=1)中包含图片标识符。
  • 在JSP / Servlet世界中,您可以让Servlet侦听某个URL模式,如/images/*,这样您就可以在特定的URL上执行某些Java代码。
  • 图片是二进制数据,将从数据库中获取byte[]InputStreamJDBC API提供ResultSet#getBytes()ResultSet#getBinaryStream()这个,JPA API为此提供了@Lob
  • 在Servlet中,您可以通过Java IO方式将此byte[]InputStream写入回复的OutputStream
  • 需要指示客户端数据应作为图像处理,因此至少需要设置Content-Type响应头。您可以根据图片文件扩展名通过ServletContext#getMimeType()获取正确的图片文件扩展名,您可以通过<mime-mapping>中的web.xml进行扩展和/或覆盖。

那应该是它。它几乎写了代码本身。让我们从HTML开始(在JSP中):

<img src="${pageContext.request.contextPath}/images/foo.png">
<img src="${pageContext.request.contextPath}/images/bar.png">
<img src="${pageContext.request.contextPath}/images/baz.png">

在使用EL进行迭代时,您可以根据需要使用JSTL动态设置src

<c:forEach items="${imagenames}" var="imagename">
    <img src="${pageContext.request.contextPath}/images/${imagename}">
</c:forEach>

然后定义/创建一个servlet,它监听/images/*的URL模式的GET请求,下面的例子使用普通的vanilla JDBC来完成这项工作:

@WebServlet("/images/*")
public class ImageServlet extends HttpServlet {

    // content=blob, name=varchar(255) UNIQUE.
    private static final String SQL_FIND = "SELECT content FROM Image WHERE name = ?";

    @Resource(name="jdbc/yourDB") // For Tomcat, define as <Resource> in context.xml and declare as <resource-ref> in web.xml.
    private DataSource dataSource;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String imageName = request.getPathInfo().substring(1); // Returns "foo.png".

        try (Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_FIND)) {
            statement.setString(1, imageName);

            try (ResultSet resultSet = statement.executeQuery()) {
                if (resultSet.next()) {
                    byte[] content = resultSet.getBytes("content");
                    response.setContentType(getServletContext().getMimeType(imageName));
                    response.setContentLength(content.length);
                    response.getOutputStream().write(content);
                } else {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
                }
            }
        } catch (SQLException e) {
            throw new ServletException("Something failed at SQL/DB level.", e);
        }
    }

}

就是这样。如果您担心HEAD和缓存标头并正确响应这些请求,请使用此abstract template for static resource servlet

另见:

答案 1 :(得分:6)

我建议你解决两个问题。有两个问题和答案都与这两个问题有关。

  1. 如何从MySQL加载blob

    例如参见Retrieve image stored as blob

  2. 如何动态显示图像

    例如参见Show thumbnail dynamically

答案 2 :(得分:0)

尝试刷新并关闭输出流(如果未显示)。         Blob image = rs.getBlob(ImageColName);         InputStream in = image.getBinaryStream();         //将blob输出到HttpServletResponse         response.setContentType("image/jpeg");         BufferedOutputStream o = new BufferedOutputStream(response.getOutputStream());

    byte by[] = new byte[32768];
    int index = in.read(by, 0, 32768);
    while (index != -1) {
        o.write(by, 0, index);
        index = in.read(by, 0, 32768);
    }
    o.flush();
    o.close();

答案 3 :(得分:-2)

您还可以创建自定义标签以显示图像。

1)创建自定义标记java类和tld文件。

2)写入逻辑来显示图像,如Base64将字节[]转换为字符串。

因此无论您是在单个jsp页面中只显示一个图像还是多个图像,它都会用于每个图像。

答案 4 :(得分:-2)

我使用了SQL SERVER数据库,所以答案的代码是一致的。您所要做的就是在jsp页面中包含一个<img>标记,并从其src属性中调用一个servlet,如下所示

<img width="200" height="180" src="DisplayImage?ID=1">

这里1是数据库中图像的唯一ID,ID是变量。我们在servlet中收到此变量的值。在servlet代码中,我们从表中的正确列中获取二进制流输入。那就是你的图像存储在哪一列中。在我的代码中,我使用了第三列,因为我的图像在第三列中存储为二进制数据。从表中检索输入流数据后,我们在输出流中读取其内容,以便可以在屏幕上写入。这是它

import java.io.*;  
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.*;  
import javax.servlet.http.*;  
import model.ConnectionManager;
public class DisplayImage extends HttpServlet { 
    public void doGet(HttpServletRequest request,HttpServletResponse response)  
             throws IOException  
    { 
    Statement stmt=null;
    String sql=null;
    BufferedInputStream bin=null;
    BufferedOutputStream bout=null;
    InputStream in =null;

    response.setContentType("image/jpeg");  
    ServletOutputStream out;  
    out = response.getOutputStream();  
    Connection conn = ConnectionManager.getConnection();

    int ID = Integer.parseInt(request.getParameter("ID"));
        try {
            stmt = conn.createStatement();
            sql = "SELECT * FROM IMAGETABLE WHERE ID="+ID+"";
            ResultSet result = stmt.executeQuery(sql);
            if(result.next()){
                in=result.getBinaryStream(3);//Since my data was in third column of table.
            }
            bin = new BufferedInputStream(in);  
            bout = new BufferedOutputStream(out);  
            int ch=0;   
            while((ch=bin.read())!=-1)  
                {  
                bout.write(ch);  
            }  

        } catch (SQLException ex) {
            Logger.getLogger(DisplayImage.class.getName()).log(Level.SEVERE, null, ex);
        }finally{
        try{
            if(bin!=null)bin.close();  
            if(in!=null)in.close();  
            if(bout!=null)bout.close();  
            if(out!=null)out.close();
            if(conn!=null)conn.close();
        }catch(IOException | SQLException ex){
            System.out.println("Error : "+ex.getMessage());
        }
    }


    }  
}  

执行jsp或html文件后,您将在屏幕上看到图像。