Как получить и отобразить изображения из базы данных на странице JSP?

Как я могу получить и отобразить изображения из базы данных на странице JSP?

6 ответов

Давайте посмотрим по шагам, что должно произойти:

  • JSP - это в основном технология просмотра, которая должна генерировать HTML-вывод.
  • Чтобы отобразить изображение в HTML, вам нужен HTML <img> элемент.
  • Чтобы он мог найти изображение, вам нужно указать его src приписывать.
  • src атрибут должен указывать на действительный http:// URL и, следовательно, не путь к файловой системе локального диска file:// поскольку это никогда не будет работать, когда сервер и клиент работают на физически разных машинах.
  • URL-адрес изображения должен иметь идентификатор изображения в любом из путей запроса (например, http://example.com/context/images/foo.png) или в качестве параметра запроса (например, http://example.com/context/images?id=1).
  • В мире JSP/Servlet вы можете позволить сервлету прослушивать определенный шаблон URL, такой как /images/*, так что вы можете просто выполнить некоторый Java-код по конкретным URL-адресам.
  • Изображения являются двоичными данными и должны быть получены как byte[] или же InputStream из БД, JDBC API предлагает ResultSet#getBytes() а также ResultSet#getBinaryStream() для этого и JPA API предлагает @Lob за это.
  • В сервлете вы можете просто написать это byte[] или же InputStream к OutputStream ответа обычным способом Java IO.
  • Клиентская сторона должна быть проинструктирована, что данные должны обрабатываться как изображение, таким образом, по крайней мере, 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">

Вы можете при необходимости также динамически установить src с EL при итерации с использованием JSTL:

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

Затем определите / создайте сервлет, который прослушивает запросы GET по шаблону URL /images/* В приведенном ниже примере для работы используется простой ванильный 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 и заголовках кэширования и о правильном ответе на эти запросы, используйте этот абстрактный шаблон для сервлета статических ресурсов.

Смотрите также:

Я предлагаю вам решить это как две проблемы. Есть несколько вопросов и ответов, связанных с обоими.

  1. Как загрузить блоб из MySQL

    Смотрите, например, Получить изображение, сохраненное в виде BLOB-объекта

  2. Как отображать изображение динамически

    Смотрите, например, Показать миниатюру динамически

Я написал и настроил код в JSP, используя базу данных Oracle. Надеюсь, это поможет.

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

    }

}

Вы также можете создать собственный тег для отображения изображения.

1) создать пользовательский тег класса Java и файл TLD.

2) написать логику для отображения изображения, как преобразование байта [] в строку с помощью Base64.

поэтому он используется для каждого изображения независимо от того, отображается ли на одной странице JSP только одно или несколько изображений.

Попробуйте очистить и закрыть выходной поток, если он не отображается. Blob image = rs.getBlob(ImageColName);InputStream in = image.getBinaryStream(); // Вывод большого двоичного объекта в 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();

Я использовал базу данных SQL SERVER, поэтому код ответа соответствует. Все, что вам нужно сделать, это включить <img> пометить на своей странице JSP и вызвать сервлет из его атрибута src, как это

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

Здесь 1 - уникальный идентификатор изображения в базе данных, а идентификатор - переменная. Получаем значение этой переменной в сервлете. В коде сервлета мы берем входные данные двоичного потока из правильного столбца в таблице. То есть в каком столбце хранится ваше изображение. В моем коде я использовал третий столбец, потому что мои изображения хранятся в виде двоичных данных в третьем столбце. После извлечения данных входного потока из таблицы мы читаем его содержимое в выходном потоке, чтобы его можно было записать на экране. Вот

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 вы увидите изображение на экране.

Другие вопросы по тегам