I want to display all my products info, but I have problem with showing a product image. I get my products from DB and then I add them to Model
, but don't know why only image don't display. In HTML it looks like this:
<div class="row">
<div class="col-sm-3 my-2 d-flex align-content-stretch flex-wrap" th:each="product : ${products}">
<div class="card">
<img class="card-img-top" th:src="${product.image}">
<div class="card-body">
<h5 class="card-title" th:text="${product.name}">Product name</h5>
<p class="card-text" th:text="${product.description}">Product summary</p>
<p class="card-text" th:text="${product.cost}">Product summary</p>
</div>
</div>
</div>
</div>
In controller I add all the products like this:
@GetMapping("/")
public String getHomePage(Model model) {
model.addAttribute("products", productRepository.findAll());
return "home";
}
And the product model is as shown:
@Entity
@Getter
public class Product extends BaseEntity {
private String name;
private String description;
@OneToOne
private Category category;
private double cost;
@Lob
private byte[] image;
public Product() {
super();
}
public Product(String name, String description, Category category, double cost, byte[] image) {
this();
this.name = name;
this.description = description;
this.category = category;
this.cost = cost;
this.image = image;
}
}
My problem is that I want to display multiple images at one time.
BTW, I know that the findAll
method is not a good choose, but It is only for testing proposes. Later I want to implement pagination, but first how to display, a byte array image?
Handling User Input We use th:action to provide the form action URL and th:object to specify an object to which the submitted form data will be bound. Individual fields are mapped using the th:field=”*{name}” attribute, where the name is the matching property of the object.
Request parameters can be easily accessed in Thymeleaf views. Request parameters are passed from the client to server like: https://example.com/query?q=Thymeleaf+Is+Great! In the above example if parameter q is not present, empty string will be displayed in the above paragraph otherwise the value of q will be shown.
I'm answering this old question, in the hope of helping someone with the same need.
In order to show image using bytes, you have to create a controller action with the role of showing the image:
@GetMapping("/product/image/{id}")
public void showProductImage(@PathVariable String id
HttpServletResponse response) throws IOException {
response.setContentType("image/jpeg"); // Or whatever format you wanna use
Product product = productRepository.findById(id);
InputStream is = new ByteArrayInputStream(product.getImage());
IOUtils.copy(is, response.getOutputStream());
}
Thus, you can simply show your image with:
<div class="row">
<div class="col-sm-3 my-2 d-flex align-content-stretch flex-wrap" th:each="product : ${products}">
<div class="card">
<img class="card-img-top" th:src="@{'product/image/' + @{product.image}}">
<div class="card-body">
<h5 class="card-title" th:text="${product.name}">Product name</h5>
<p class="card-text" th:text="${product.description}">Product summary</p>
<p class="card-text" th:text="${product.cost}">Product summary</p>
</div>
</div>
</div>
PS: you better use the wrapper Byte in spite of byte for your image attribute. This will let you manage cases of no image (null)
Edit: The last line of showProductImage method is copying InputStream to OutputStream (check IOUtils doc for more details)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With