How to retrieve and display images from a database in a JSP page?
Asked Answered
P

6

33

How can I retrieve and display images from a database in a JSP page?

Parnassus answered 26/2, 2010 at 8:49 Comment(0)
P
71

Let's see in steps what should happen:

  • JSP is basically a view technology which is supposed to generate HTML output.
  • To display an image in HTML, you need the HTML <img> element.
  • To let it locate an image, you need to specify its src attribute.
  • The src attribute needs to point to a valid http:// URL and thus not a local disk file system path file:// as that would never work when the server and client run at physically different machines.
  • The image URL needs to have the image identifier in either the request path (e.g. http://example.com/context/images/foo.png) or as request parameter (e.g. http://example.com/context/images?id=1).
  • In JSP/Servlet world, you can let a Servlet listen on a certain URL pattern like /images/*, so that you can just execute some Java code on specific URL's.
  • Images are binary data and are to be obtained as either a byte[] or InputStream from the DB, the JDBC API offers the ResultSet#getBytes() and ResultSet#getBinaryStream() for this, and JPA API offers @Lob for this.
  • In the Servlet you can just write this byte[] or InputStream to the OutputStream of the response the usual Java IO way.
  • The client side needs to be instructed that the data should be handled as an image, thus at least the Content-Type response header needs to be set as well. You can obtain the right one via ServletContext#getMimeType() based on image file extension which you can extend and/or override via <mime-mapping> in web.xml.

That should be it. It almost writes code itself. Let's start with HTML (in 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">

You can if necessary also dynamically set src with EL while iterating using JSTL:

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

Then define/create a servlet which listens on GET requests on URL pattern of /images/*, the below example uses plain vanilla JDBC for the job:

@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);
        }
    }

}

That's it. In case you worry about HEAD and caching headers and properly responding on those requests, use this abstract template for static resource servlet.

See also:

Printery answered 26/2, 2010 at 11:49 Comment(7)
@Printery : How can this be done in Spring Framework. The controller returns only a view. How can the byte stream be returned.Erna
@Ashwin: Just the same way. Spring doesn't forbid you to create another servlet.Printery
I have done a small change because if you are using spring MVC u need to add return also otherwise we will get error "at org.apache.catalina.connector.ResponseFacade.setBufferSize(ResponseFacade.java:233)" since a response is already committed, A response is committed when a response header has been set before etcSororate
@Pulkit: Question and answer are based on plain JSP/Servlet, not Spring MVC.Printery
@BalusC: I know Sir, I mentioned also that "if you are using MVC" actually a user may come across this post when he is using MVC (like in my case I am using MVC).Sororate
@Pulkit: Plain JSP/Servlet can also be used as MVC. The current question is not about Spring MVC framework at all. Just look for the right question if you really need to post a Spring MVC-targeted answer/comment.Printery
for those looking for hibernate based solution and not JDBC have a look at stackoverflow.com/questions/9049488/…Hyperkeratosis
C
6

I suggest you address that as two problems. There are several questions and answer related to both.

  1. How to load blob from MySQL

    See for instance Retrieve image stored as blob

  2. How to display image dynamically

    See for instance Show thumbnail dynamically

Concomitant answered 26/2, 2010 at 9:10 Comment(0)
C
0

I've written and configured the code in JSP using Oracle database. Hope it will help.

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());
            }
        }

    }

}
Chanellechaney answered 24/12, 2022 at 12:49 Comment(0)
V
-1

Try to flush and close the output stream if it does not display. Blob image = rs.getBlob(ImageColName); InputStream in = image.getBinaryStream(); // Output the blob to the 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();
Vibrate answered 19/2, 2019 at 10:14 Comment(0)
N
-2

I used SQL SERVER database and so the answer's code is in accordance. All you have to do is include an <img> tag in your jsp page and call a servlet from its src attribute like this

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

Here 1 is unique id of image in database and ID is a variable. We receive value of this variable in servlet. In servlet code we take the binary stream input from correct column in table. That is your image is stored in which column. In my code I used third column because my images are stored as binary data in third column. After retrieving input stream data from table we read its content in an output stream so it can be written on screen. Here is it

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());
        }
    }


    }  
}  

After the execution of your jsp or html file you will see the image on screen.

Nelrsa answered 4/4, 2016 at 11:57 Comment(3)
WARNING: This code is not threadsafe, is leaking resources, and is memory inefficient. For the correct approach see the currently accepted answer.Printery
Dear BalusC, Can you make this code thread safe and remove the other shortcomings stated by you, please.Nelrsa
@BalusC: I have updated my answer. It is perfect now.Nelrsa
P
-5

You can also create custom tag for displaying image.

1) create custom tag java class and tld file.

2) write logic to display image like conversion of byte[] to string by Base64.

so it is used for every image whether you are displaying only one image or multiple images in single jsp page.

Puleo answered 26/8, 2015 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.