Reputation: 23
I've been trying to display an image using thymeleaf for awhile and having issues with it saving it as a byte array was no problem, however displaying it is extremely (for me at least) I followed a post with the question that was asked about it and had no results sadly, was hoping someone could help me with this problem
Controller trying to display the image
@GetMapping("/home")
public String index(Model model){
model.addAttribute("clothingItems", itemService.findAll());
return "index";
}
@GetMapping("/display/image/{id}")
public void displayItemImage(@PathVariable int id, HttpServletResponse response) throws IOException{
response.setContentType("image/*");
Item item = itemService.findItemById(id);
InputStream is = new ByteArrayInputStream(item.getImage());
IOUtils.copy(is, response.getOutputStream());
}
My Entity class
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "post")
private String text;
@Lob
@Column(name = "img")
private byte[] image;
@OneToOne(cascade = {CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH})
@JoinColumn(name = "category_id")
private Category category;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
Trying to display it with thymeleaf
<div class="category-1">
<h2>Headwear</h2>
<div class="image-container" th:each="clothing : ${clothingItems}">
<img th:src="@{'display/image/' + @{clothing.image}}">
</div>
</div>
I tried following this post How to display byte array from a model in Thymeleaf and ended up with an empty image
im also getting a NumberFormatException when I try to open the empty image in a new tab
Upvotes: 1
Views: 920
Reputation: 312
In your thymeleaf template for the code
<img th:src="@{'display/image/' + @{clothing.image}}">
The src
should point to @{'/display/image/'}
you need to insert '/' that specifies you are referring to the root of your application also instead of @{clothing.image}
it should be ${clothing.image}
as it's a variable, not a link.
So the above line code of should be
<img th:src="@{'/display/image/' + ${clothing.id}}">
Try this in your displayItemImage
method it's not advisable to directly write the content to the response
entity and also change the MIME-TYPE to image/png
or image/jpeg
. Here's a better approach.
@GetMapping("/display/image/{id}")
public ResponseEntity<byte[]> displayItemImage(@PathVariable int id) {
Item item = itemService.findItemById(id);
byte[] image = item.getImage();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<>(image, headers, HttpStatus.OK);
}
For testing the method I have used H2 database. Here's the test code with the results.
@SpringBootTest
class ShoppingSiteApplicationTests {
@Autowired
ItemService itemService;
@Autowired
private UserController yourController;
private MockMvc mockMvc;
@Test
void testMethod() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(yourController).build();
byte [] mockByte = {0x01, 0x02, 0x03};
Item item = new Item();
item.setImage(mockByte);
itemService.saveItem(item);
MvcResult result = mockMvc.perform(get("/display/image/" + item.getId()))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.IMAGE_JPEG))
.andReturn();
byte[] responseBody = result.getResponse().getContentAsByteArray();
assertArrayEquals(item.getImage(), responseBody);
}
}
Here's the live result from your Github Repository you can see the image displayed. The problem may be in the MYSQL
setup or so, if yes please raise another question with the code. Hope it helps
Upvotes: 1