Spring MVC 如何在Thymeleaf中显示模型的字节数组

zbdgwd5y  于 2022-11-14  发布在  Spring
关注(0)|答案(3)|浏览(151)

我想显示我所有的产品信息,但我在显示产品图片时遇到问题。我从DB中获取产品,然后将它们添加到Model中,但不知道为什么只有图片不显示。在HTML中,它看起来像这样:

  1. <div class="row">
  2. <div class="col-sm-3 my-2 d-flex align-content-stretch flex-wrap" th:each="product : ${products}">
  3. <div class="card">
  4. <img class="card-img-top" th:src="${product.image}">
  5. <div class="card-body">
  6. <h5 class="card-title" th:text="${product.name}">Product name</h5>
  7. <p class="card-text" th:text="${product.description}">Product summary</p>
  8. <p class="card-text" th:text="${product.cost}">Product summary</p>
  9. </div>
  10. </div>
  11. </div>
  12. </div>

在控制器中,我添加了所有这样的产品:

  1. @GetMapping("/")
  2. public String getHomePage(Model model) {
  3. model.addAttribute("products", productRepository.findAll());
  4. return "home";
  5. }

产品型号如图所示:

  1. @Entity
  2. @Getter
  3. public class Product extends BaseEntity {
  4. private String name;
  5. private String description;
  6. @OneToOne
  7. private Category category;
  8. private double cost;
  9. @Lob
  10. private byte[] image;
  11. public Product() {
  12. super();
  13. }
  14. public Product(String name, String description, Category category, double cost, byte[] image) {
  15. this();
  16. this.name = name;
  17. this.description = description;
  18. this.category = category;
  19. this.cost = cost;
  20. this.image = image;
  21. }
  22. }

我的问题是我想一次显示多个图像。顺便说一句,我知道findAll方法不是一个好的选择,但它只是为了测试建议。稍后我想实现分页,但首先如何显示,一个字节数组的图像?

0x6upsns

0x6upsns1#

我在回答这个老问题,希望能帮助有同样需要的人。
为了使用字节显示图像,您必须创建一个具有显示图像角色的控制器操作:

  1. @GetMapping("/product/image/{id}")
  2. public void showProductImage(@PathVariable String id
  3. HttpServletResponse response) throws IOException {
  4. response.setContentType("image/jpeg"); // Or whatever format you wanna use
  5. Product product = productRepository.findById(id);
  6. InputStream is = new ByteArrayInputStream(product.getImage());
  7. IOUtils.copy(is, response.getOutputStream());
  8. }

因此,您可以简单地显示图像:

  1. <div class="row">
  2. <div class="col-sm-3 my-2 d-flex align-content-stretch flex-wrap" th:each="product : ${products}">
  3. <div class="card">
  4. <img class="card-img-top" th:src="@{'product/image/' + @{product.image}}">
  5. <div class="card-body">
  6. <h5 class="card-title" th:text="${product.name}">Product name</h5>
  7. <p class="card-text" th:text="${product.description}">Product summary</p>
  8. <p class="card-text" th:text="${product.cost}">Product summary</p>
  9. </div>
  10. </div>
  11. </div>

PS:你最好使用 Package 器Byte,尽管你的图像属性是byte。这将让你管理没有图像的情况(空)
Edit:showProductImage方法的最后一行是将InputStream复制到OutputStream(查看IOUtils文档以了解更多详细信息)

展开查看全部
new9mtju

new9mtju2#

在使用Sping Boot 时遇到了同样的问题,我不相信使用HttpServletResponse在单独的请求中获取图像,因为我们已经检索了模型属性中包含的图像字节数组,我想知道:如何从字节数组本身加载图像?
通过将图像字节数组转换为base64字符串并将其传递给JavaScript以填充图像预览元素,找到了解决方案:

在Java中

添加一个额外的String属性,表示图像的base64编码值:

  1. private String imageBase64;
  2. public String getImageBase64() {
  3. return imageBase64;
  4. }
  5. public void setImageBase64(String imageBase64) {
  6. this.imageBase64 = imageBase64;
  7. }

从数据库中获取对象后,增加一个额外的步骤,从图像字节数组进行base64转换,如下所示:

  1. import java.util.Base64;
  2. import org.apache.commons.lang3.ArrayUtils;
  3. if(ArrayUtils.isNotEmpty(product.getImage())) {
  4. String imageBase64 = Base64.getEncoder().encodeToString(product.getImage());
  5. productDTO.setImageBase64(imageBase64);
  6. }

在JSP/HTML中

添加一个包含图像的base64字符串的额外隐藏字段

  1. <input type="hidden" id="imageBase64" value="${product.imageBase64}" readonly></input>
  2. <img id="imagePreview" src="#" alt="Background image" />

在JavaScript中

通过隐藏字段中的base64值设置图像内容

  1. var imageBase64 = $('#imageBase64').val();
  2. var imagePreview= document.getElementById('imagePreview');
  3. if(imagePreview) {
  4. imagePreview.src = "data:image/png;base64," + imageBase64;
  5. }

此外,还可以将图像存储为Base64字符串并摆脱自定义转换阶段...

展开查看全部
yptwkmov

yptwkmov3#

这就是我的工作,转换图像到Base64,并注入到Thymeleaf使用一个Map,例如

  1. Map<Long, String> productBase64Images = new HashMap<>();
  2. for(Product product: products){
  3. productBase64Images.put(product.getId(), Base64.getEncoder().encodeToString(product.getImage()));
  4. }
  5. model.addAttribute("images", productBase64Images);

使用以下方式显示图像:<img th:src="${'data:image/jpeg;charset=utf-8;base64,' + images.get(product.id)}" alt="">

相关问题