Issue
I'm currently making a website with Java EE, using maven, thymeleaf, and hosting it on heroku (database addon is JawsDBMySQL). I've created a simple html page in order to check the good working of it. Of course it works perfectly for a local upload : the file goes to a folder I've designed.
In my data base the path to my local storage is stored as a string. I've also add a longblob column, but I did not really understood how to use it.
Now I want to store files into my database when my application is online.
I didn't found solution that perfectly match with my issue, but I'm quite sure it is pretty simple.
Hoping I have been clear enough,
thanks for your help.
Servlet that display a page on /home2 with the list of the pictures
package marquise.servlets;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import marquise.services.InformationLibrary;
@WebServlet("/home2")
public class HomeServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = 5402133218271984030L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
//Country countryFilter = (Country) req.getSession().getAttribute("countryFilter");
context.setVariable("images", InformationLibrary.getInstance().listAllImages());
//context.setVariable("cities", CityService.getInstance().listAllCities(countryFilter));
//context.setVariable("countries", Country.values());
//context.setVariable("countryFilterSelected", countryFilter);
templateEngine.process("home", context, resp.getWriter());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String countryString = req.getParameter("countryFilter");
resp.sendRedirect("home2");
}
}
Servlet for the path
@WebServlet("/imagepicture")
public class CityPictureServlet extends AbstractGenericServlet2 {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer imageId = Integer.parseInt(req.getParameter("id"));
Path picturePath = InformationLibrary.getInstance().getPicturePatch(imageId);
Files.copy(picturePath, resp.getOutputStream());
}
}
servlet that print image details (not important right now) package marquise.servlets;
@WebServlet("/detail")
public class CityDetailServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = 8559083626521311046L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
Integer idImage = Integer.parseInt(req.getParameter("id"));
context.setVariable("image", InformationLibrary.getInstance().getImage(idImage));
//context.setVariable("comments", InformationLibrary.getInstance().listCommentsByCity(idCity));
context.setVariable("comments", InformationLibrary.getInstance().listAllImages());
templateEngine.process("imagedetail", context, resp.getWriter());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer cityId = Integer.parseInt(req.getParameter("id"));
resp.sendRedirect(String.format("detail?id=%d", cityId));
resp.sendRedirect("home2");
}
}
HTML page displaying the list of my images
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>City Explorer</title>
<link rel="stylesheet" href="bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="fontawesome/css/font-awesome.min.css">
<link rel="stylesheet" href="css/custom.css">
</head>
<body>
<header th:replace="~{common::header}"></header>
<div id="mainContent" class="container-fluid">
<section class="cityfilters">
<h3>Filters</h3>
<form class="form-inline" method="post">
<div class="form-group">
<label for="countryInput">Country</label>
<select class="form-control" id="countryInput" name="countryFilter">
<option value="">All countries</option>
<option th:each="country : ${countries}" th:value="${country}" th:selected="${countryFilterSelected} == ${country}">[[${country.label}]]</option>
</select>
</div>
<input type="submit" class="btn btn-default" value="Filter">
</form>
</section>
<section class="citylist">
<article class="citybox" th:each="image : ${images}">
<h3>
[[${image.name}]]
<a th:href="'deleteimage?id='+${image.id}" class="btn btn-xs btn-danger pull-right">
<i class="fa fa-times" aria-hidden="true"></i>
</a>
</h3>
<p th:text="${image.summary}" class="summary"></p>
<div class="btn-toolbar actionbar" role="toolbar">
<div class="btn-group" role="group">
<a th:href="'detail?id='+${image.id}" class="btn btn-primary"><i
class="fa fa-eye" aria-hidden="true"></i> See details</a>
</div>
</div>
<aside class="cityPhoto">
<img th:src="'imagepicture?id='+${image.id}" th:alt="'Vignette '+${image.name}">
</aside>
</article>
</section>
</div>
</body>
</html>
My Library Class with the path to my computer
public class InformationLibrary {
private static class InformationLibraryHolder{
private final static InformationLibrary instance = new InformationLibrary();
}
public static InformationLibrary getInstance(){
return InformationLibraryHolder.instance;
}
private InformationDao informationDao = new InformationDaoImpl();
private UtilisateurDao utilisateurDao = new UtilisateurDaoImpl();
private CommentaireDao commentaireDao = new CommentaireDaoImpl();
private ArticleDao articleDao = new ArticleDaoImpl();
private IdentifiantDao identifiantDao = new IdentifiantDaoImpl();
private ImageDao imageDao = new ImageDao();
private static final String PICTURE_MAIN_DIRECTORY = "/Users/louiscauvray/git/projet/src/main/resources";
private ElementsSiteDao elementsSiteDao = new ElementsSiteDao();
private InformationLibrary() {
}
//Recuperer les informations sur les utilisateurs
public List<Information> listFilms() {
return informationDao.listInformations();
}
public Information getInformation(Integer id) {
return informationDao.getInformation(id);
}
public Information addInformation(Information information) {
return informationDao.addInformation(information);
}
public List<Utilisateur> listUtilisateurs() {
return utilisateurDao.listUtilisateurs();
}
public Utilisateur getUtilisateur(Integer id) {
return utilisateurDao.getUtilisateur(id);
}
public Utilisateur getUtilisateurByNom(String nom){
return utilisateurDao.getUtilisateurByNom(nom);
}
public Utilisateur addUtilisateur(String nom, String prenom) {
return utilisateurDao.addUtilisateur(nom, prenom);
}
//Gerer les commentaires visible en backoffice
public List<Commentaire> listCommentaires(){
return commentaireDao.listCommentaires();
}
public Commentaire addCommentaire(String email ,String commentaire){
return commentaireDao.addCommentaire(email, commentaire);
}
public List<Article> listArticles(){
return articleDao.listArticles();
}
public Article addArticle(String title, String texte, LocalDate datePublication, String auteur) {
return articleDao.addArticle(title, texte, datePublication, auteur);
}
public Identifiant getIdentifiant(String login, String motDePasse){
return identifiantDao.getIdentifiant(login, motDePasse);
}
//Methode pour appeler les image et les chemins des images
public List<Image> listAllImages() {
return imageDao.listImages();
}
public Image getImage(Integer id) {
if(id == null) {
throw new IllegalArgumentException("Image id must be provided.");
}
return imageDao.getImage(id);
}
public void addImage(Image newImage, Part picture) throws IOException {
if(newImage == null){
throw new IllegalArgumentException("An image must be provided.");
}
if(newImage.getName() == null || "".equals(newImage.getName())) {
throw new IllegalArgumentException("An image must have a name.");
}
if(newImage.getSummary() == null || "".equals(newImage.getSummary())) {
throw new IllegalArgumentException("An image must have a summary.");
}
if(picture == null){
throw new IllegalArgumentException("An image must contain a picture.");
}
Path picturePath = Paths.get(PICTURE_MAIN_DIRECTORY, picture.getSubmittedFileName());
imageDao.addImage(newImage, picturePath.toString());
Files.copy(picture.getInputStream(), picturePath);
}
public Path getPicturePatch(Integer imageId) {
String picturePathString = imageDao.getPicturePath(imageId);
if(picturePathString == null) {
return getDefaultPicturePath();
} else {
Path picturePath = Paths.get(imageDao.getPicturePath(imageId));
if(Files.exists(picturePath)) {
return picturePath;
} else {
return getDefaultPicturePath();
}
}
}
private Path getDefaultPicturePath() {
try {
return Paths.get(this.getClass().getClassLoader().getResource("city-no-photo.png").toURI());
} catch (URISyntaxException e) {
return null;
}
}
// ElementsSite Dao
public void modifierElementTexte(String idElement, String contenuElement) {
elementsSiteDao.modifierElementTexte(idElement, contenuElement);
}
public void modifierElementImage(String idElement, String contenuElement, String cheminElement) {
elementsSiteDao.modifierElementImage(idElement, contenuElement, cheminElement);
}
public ElementsSite getElementById(String id) {
return elementsSiteDao.getElementById(id) ;
}
}
My Dao Class where methods to display images are defined
import marquise.daos.impl.DataSourceProvider;
import marquise.exceptions.CityExplorerRuntimeException;
import marquise.projos.Image;
public class ImageDao {
public List<Image> listImages() {
List<Image> images = new ArrayList<Image>();
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM image ORDER BY name")) {
while (resultSet.next()) {
images.add(
new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary")));
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return images;
}
public Image getImage(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary"));
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
public void addImage(Image newImage, String picturePath) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO image(name, summary, picture) VALUES (?, ?, ?)")) {
statement.setString(1, newImage.getName());
statement.setString(2, newImage.getSummary());
statement.setString(3, picturePath);
statement.executeUpdate();
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
}
public String getPicturePath(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT picture FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getString("picture");
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
}
Solution
Finally I found a solution to my problem :
I added a longblob column into my data base table, and changed a bit my method.
Here is my final code if you need it :
The DaoClass :
package marquise.daos;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import marquise.daos.impl.DataSourceProvider;
import marquise.exceptions.CityExplorerRuntimeException;
import marquise.projos.Image;
public class ImageDao {
public List<Image> listImages() {
List<Image> images = new ArrayList<Image>();
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM image ORDER BY name")) {
while (resultSet.next()) {
images.add(
new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary")));
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return images;
}
public Image getImage(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary"));
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
public void addImage(Image newImage, String picturePath) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO image(name, summary, picture) VALUES (?, ?, ?)")) {
statement.setString(1, newImage.getName());
statement.setString(2, newImage.getSummary());
statement.setString(3, picturePath);
statement.executeUpdate();
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
}
public void addImage(Image img, InputStream is){
try(Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO image(name, summary, image) VALUES (?, ?, ?)")) {
statement.setString(1, img.getName());
statement.setString(2, img.getSummary());
statement.setBinaryStream(3, is);
statement.executeUpdate();
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
}
public String getPicturePath(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT picture FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getString("picture");
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
public InputStream getPicture(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT image FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getBinaryStream("image");
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
/*public InputStream getPicture(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT image FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getBlob("image") == null ? null : resultSet.getBlob("image").getBinaryStream();
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}*/
}
the addimage servlet :
package marquise.servlets;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import marquise.projos.Image;
import marquise.services.InformationLibrary;
@WebServlet("/addimage")
@MultipartConfig
public class ImageAddServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = -3497793006266174453L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
if(req.getSession().getAttribute("imageCreationError") != null) {
context.setVariable("errorMessage", req.getSession().getAttribute("imageCreationError"));
context.setVariable("image", (Image) req.getSession().getAttribute("imageCreationData"));
req.getSession().removeAttribute("imageCreationError");
req.getSession().removeAttribute("imageCreationData");
} else {
context.setVariable("image", new Image(null, null, null));
}
context.setVariable("countries", context);
templateEngine.process("connectedUsers/imageadd", context, resp.getWriter());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String summary = req.getParameter("summary");
Part imagePicture = req.getPart("picture");
Image newImage = new Image(null, name, summary);
InputStream is = imagePicture.getInputStream();
try {
InformationLibrary.getInstance().addImage(newImage, is);
resp.sendRedirect("certificatsAdmin");
} catch (IllegalArgumentException|IOException e) {
req.getSession().setAttribute("imageCreationError", e.getMessage());
req.getSession().setAttribute("imageCreationData", newImage);
resp.sendRedirect("addimage");
}
}
}
The listImage servlet :
package marquise.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import marquise.services.InformationLibrary;
@WebServlet("/certificatsAdmin")
public class listeCertifServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = 5402133218271984030L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
HttpSession session=req.getSession(false);
if(session != null){}
else{
resp.sendRedirect("connexion");
out.println("Veuillez entre un mot de passe correct");
}
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
//Country countryFilter = (Country) req.getSession().getAttribute("countryFilter");
context.setVariable("images", InformationLibrary.getInstance().listAllImages());
//context.setVariable("cities", CityService.getInstance().listAllCities(countryFilter));
//context.setVariable("countries", Country.values());
//context.setVariable("countryFilterSelected", countryFilter);
templateEngine.process("admin/certificatsAdmin", context, resp.getWriter());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String countryString = req.getParameter("countryFilter");
resp.sendRedirect("certificatsAdmin");
}
}
Answered By - Louis-Côme Auvray
Answer Checked By - Marilyn (JavaFixing Volunteer)