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

2022-09-01 11:25:46

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


答案 1

让我们在步骤中看看应该发生什么:

  • JSP基本上是一种视图技术,应该生成HTML输出。
  • 要在 HTML 中显示图像,您需要 HTML 元素。<img>
  • 要让它定位图像,您需要指定其属性。src
  • 该属性需要指向有效的 URL,因此不需要本地磁盘文件系统路径,因为当服务器和客户端在物理上不同的计算机上运行时,该路径将永远不会起作用。srchttp://file://
  • 图像 URL 需要在请求路径(例如 )或作为请求参数(例如 )中具有图像标识符。http://example.com/context/images/foo.pnghttp://example.com/context/images?id=1
  • 在 JSP/Servlet 世界中,您可以让 Servlet 监听某个 URL 模式,例如 ,这样您就可以在特定 URL 上执行一些 Java 代码。/images/*
  • 图像是二进制数据,可以作为数据库或从数据库获取,JDBC API为此提供了ResultSet#getBytes()ResultSet#getBinaryStream(),JPA API为此提供了@Lobbyte[]InputStream
  • 在Servlet中,你可以用通常的Java IO方式写这个或到响应中。byte[]InputStreamOutputStream
  • 需要指示客户端将数据作为图像进行处理,因此至少还需要设置 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">

如有必要,您还可以在使用 JSTL 迭代时使用 EL 进行动态设置:src

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

然后定义/创建一个 servlet,该 servlet 侦听 URL 模式上的 GET 请求,下面的示例使用普通的 vanilla JDBC 进行作业:/images/*

@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 和缓存标头并正确响应这些请求,请将此抽象模板用于静态资源 servlet

另请参阅:


答案 2

我建议你把这个问题作为两个问题来解决这个问题。有几个问题和答案与两者有关。

  1. 如何从 MySQL 加载 blob

    例如,请参阅 检索存储为 blob 的图像

  2. 如何动态显示图像

    例如,请参阅动态显示缩略图


推荐