我如何从数据库中检索并在JSP页面上显示图片?
让我们逐步看看应该发生的事情:
<img>
元素。src
属性。src
属性需要指向有效的http://
URL,而不是本地磁盘文件系统路径file://
,因为当服务器和客户端在物理上不同的计算机上运行时,这种方式将无法工作。http://example.com/context/images/foo.png
)或作为请求参数(例如http://example.com/context/images?id=1
)中具有图像标识符。/images/*
,以便您可以在特定的URL上执行一些Java代码。byte[]
或InputStream
,JDBC API 提供了ResultSet#getBytes()
和 ResultSet#getBinaryStream()
,JPA API 提供了@Lob
。byte[]
或InputStream
以通常的Java IO方式写入响应的OutputStream
。Content-Type
响应头。您可以通过ServletContext#getMimeType()
获取正确的MIME类型,基于图像文件扩展名,您可以通过<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,它在URL模式/images/*
上监听GET请求,下面的示例使用普通的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);
}
}
}
就是这样。如果您担心头部和缓存标头以及对这些请求做出适当的响应,请使用此静态资源servlet的抽象模板。
如何从MySQL加载blob
例如,请参见检索存储为blob的图像
如何动态显示图像
例如,请参见动态显示缩略图
我已经使用Oracle数据库在JSP中编写并配置了代码。 希望它能对你有所帮助。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
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.http.HttpSession;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class displayfetchimage
*/
@WebServlet("/displayfetchimage")
public class displayfetchimage extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public displayfetchimage() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
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 = employee.DbConnection.getDatabaseConnection();
HttpSession session = (HttpSession) request.getSession();
String ID = session.getAttribute("userId").toString().toLowerCase();
try {
stmt = conn.createStatement();
sql = "select user_image from employee_data WHERE username='" + ID + "' and rownum<=1";
ResultSet result = stmt.executeQuery(sql);
if (result.next()) {
in = result.getBinaryStream(1);// Since my data was in first 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(displayfetchimage.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());
}
}
}
// response.getWriter().append("Served at: ").append(request.getContextPath());
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, 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 = employee.DbConnection.getDatabaseConnection();
HttpSession session = (HttpSession) request.getSession();
String ID = session.getAttribute("userId").toString().toLowerCase();
try {
stmt = conn.createStatement();
sql = "select user_image from employee_data WHERE username='" + ID + "' and rownum<=1";
ResultSet result = stmt.executeQuery(sql);
if (result.next()) {
in = result.getBinaryStream(1);
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(displayfetchimage.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());
}
}
}
}
Blob image = rs.getBlob(ImageColName);
InputStream in = image.getBinaryStream();
// 将 Blob 输出到 HttpServletResponseresponse.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();
我使用了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文件后,您将在屏幕上看到图像。
您还可以创建自定义标签来显示图像。
1)创建自定义标签Java类和TLD文件。
2)编写逻辑以显示图像,例如将byte[]转换为Base64字符串。
因此,它可用于每个图像,无论您是在单个JSP页面中显示一个图像还是多个图像。
Hibernate
而非JDBC
的解决方案的人,请查看https://dev59.com/5F_Va4cB1Zd3GeqPW8zE?lq=1 - KNU