@AXAXAXAXAXAXA

Как отобразить картинку на сайте из MySQL используя Spring?

При моих попытках отображается "сломанная картинка" (иногда инспектор кода пишет, что изображение blocked: other, хотя все блокировщики отключены), либо примерно [B@7fb0c025
В БД изображение хранится как BLOB
Я новичок, поэтому не знаю всех тонкостей. Поискал на StackOverflow и Хабре ничего не помогло из того, что предлагали.
Предлагали переводить изображение из БД в Base64 и отключать блокировщики
Суть вопроса:
Я хочу, получив изображение из бд отобразить его на сайте через тег IMG, есть ли возможность на данный момент?
Модель
package com.alcoholism.photo.models;

import javax.persistence.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Entity
public class Photo {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long photo_id;

    private String photo_path;

    @Lob
    public byte[] image;



    public Long getPhoto_id() {
        return photo_id;
    }

    public void setPhoto_id(Long photo_id) {
        this.photo_id = photo_id;
    }

    public String getPhoto_path() {
        return photo_path;
    }

    public void setPhoto_path(String photo_path) {
        this.photo_path = photo_path;
    }

    public byte[] getImage(){
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }
}


Контроллер
package com.alcoholism.photo.controllers;


import com.alcoholism.photo.models.Photo;
import com.alcoholism.photo.repo.PhotoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.io.UnsupportedEncodingException;
import java.util.Base64;


@Controller
public class PhotoController {

    @Autowired
    private PhotoRepository photoRepository;



    @GetMapping("/photos")
    public String photoMain(Model model) throws UnsupportedEncodingException {
        model.addAttribute("title", "Портфолио");
        Iterable<Photo> photos = photoRepository.findAll();

        model.addAttribute("fotos", photos);

        return "photo-main";
    }

}


Репозиторий
package com.alcoholism.photo.repo;

import com.alcoholism.photo.models.Photo;
import org.springframework.data.repository.CrudRepository;

public interface PhotoRepository extends CrudRepository<Photo, Long> {


}


Шаблон
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title th:text="${title}"/>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>

<header th:insert="blocks/header :: header"></header>


  <div class="container mt-5">
    <h1>Портфолио</h1>
<!--      <img  th:src="@{'data:image/png;base64,'+${fotos}}" />-->
<!--      <h1 th:text="${fotos.photo_path}"></h1>-->
    <div th:each="el : ${fotos}">
        <h3 th:text="${el.photo_path}"></h3>
<!--         <img  th:src="@{'data:image/png;base64,'+${el}}" />-->
        <img th:src="@'data:image/png;base64,'+${el.getImage()}}">111</img>
    </div>
<!--    <img th:src="${fotos}">-->
<!--    <img src="E:\Desktop\Cyberpunk 2077\photomode_30072022_180113.png">-->
  </div>
<footer th:insert="blocks/footer :: footer"></footer>
</body>
</html>
  • Вопрос задан
  • 542 просмотра
Решения вопроса 1
ThunderCat
@ThunderCat Куратор тега MySQL
{PHP, MySql, HTML, JS, CSS} developer
Я хочу, получив изображение из бд отобразить его на сайте через тег IMG, есть ли возможность на данный момент?
Конечно есть. Вопрос только в подходе.
есть 2 основных варианта:
1) Передавать в шаблон бэйс64 строки вместо байтов. Как написал Дмитрий, вы можете это сделать прямо в модели, добавив метод кодирующий блоб в бэйс64. Или делать это в контроллере, не суть.
Минусы - вы утяжеляете шаблон, так как бэйс64 где-то на 30% больше по объему, и блокируете загрузку шаблона до полной прорисовки изображения (так как картинка "вписана" в хтмл, и пока вы ее не получите, последующие блоки просто неоткуда брать). Если их много, нагрузка будет весьма значительной.

2) Передавать линк на изображение. Естественно, линк будет вести на скрипт, а не на реальную картинку. Делаете роут для изображений, в контроллере ловите ключ картинки (айди или другой уникальный ключ из таблицы), по ней создаете модель и отдаете на клиент обычный байтовый поток. Естественно перед отправкой нужно отправить заголовок что "сейчас будет картинка". Тогда изображения будут загружаться отдельно от хтмл и грузить клиента вообще не будут.
Минусы - надо писать роут и контроллер... ну и вроде все.

Далее лирика.
Во первых - хранение картинок в бд - практика подходящая не для любого проекта, и, в большинстве случаев, это плохая практика. Почему - большая отдельная тема, как и преимущества хранения в бд. Остановимся на том что чаще всего выгоднее хранить файлы во (внезапно!) файлах. А фраза "храним картинки в базе" чаще относится к хранению в базе путей до картинки, нежели реальному сохранению их в бд.

Во вторых - второй описанный метод является весьма распространенным и обыденным, в то время как первый, в силу указанных недостатков, используется только в крайне редких случаях, например для вывода очень мелких изображений.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
azerphoenix
@azerphoenix Куратор тега Java
Java Software Engineer
Добрый день
Вам необходимо byte{} перевести в base64.

Чтобы получить массив байтов -
String image = "this is base 64 image";
byte[] photoByteArr = Base64.getDecoder().decode(String image);

Чтобы получить base64
String image = Base64.getEncoder().encodeToString(photo.getImage())

А дальше гляньте, как вставить картинку в base64 - https://stackoverflow.com/questions/8499633/how-to...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы