Comment récupérer et afficher des images d'une base de données dans une page JSP?
Voyons par étapes ce qui devrait arriver:
<img>
.src
.src
doit pointer vers une URL http://
Valide et donc pas un chemin d'accès au système de fichiers du disque local file://
Car cela ne fonctionnerait jamais lorsque le serveur et le client s'exécutent physiquement différemment. Machines.http://example.com/context/images/foo.png
) Ou comme paramètre de demande (par exemple http://example.com/context/images?id=1
)./images/*
, Afin que vous puissiez simplement exécuter du code Java sur des URL spécifiques).byte[]
Ou InputStream
à partir de la base de données, la API JDBC offre la ResultSet#getBytes()
et ResultSet#getBinaryStream()
pour cela, et API JPA propose @Lob
pour cela.byte[]
Ou InputStream
dans le OutputStream
de la réponse de la manière habituelle Java IO .Content-Type
doit également être défini. Vous pouvez obtenir le bon via ServletContext#getMimeType()
basé sur l'extension du fichier image que vous pouvez étendre et/ou remplacer via <mime-mapping>
Dans web.xml
.Ça devrait être ça. Il écrit presque le code lui-même. Commençons par HTML (dans 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">
Si nécessaire, vous pouvez également définir dynamiquement src
avec EL tout en itérant en utilisant JSTL :
<c:forEach items="${imagenames}" var="imagename">
<img src="${pageContext.request.contextPath}/images/${imagename}">
</c:forEach>
Ensuite, définissez/créez un servlet qui écoute les requêtes GET sur le modèle d'URL de /images/*
, L'exemple ci-dessous utilise du JDBC Vanilla ordinaire pour le travail:
@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);
}
}
}
C'est ça. Si vous vous inquiétez de HEAD et de la mise en cache des en-têtes et de la réponse appropriée à ces demandes, utilisez ceci modèle abstrait pour le servlet de ressource statique .
Je vous suggère de traiter cela comme deux problèmes. Il y a plusieurs questions et réponses liées aux deux.
Comment charger un blob depuis MySQL
Voir par exemple Récupérer l'image stockée sous forme de blob
Comment afficher l'image dynamiquement
Voir par exemple Afficher la vignette dynamiquement
Essayez de vider et de fermer le flux de sortie s'il ne s'affiche pas. Blob image = rs.getBlob(ImageColName);
InputStream in = image.getBinaryStream();
// Sortie du blob dans 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();