Не отображается картинка из БД

Рейтинг: -2Ответов: 1Опубликовано: 28.04.2023

Суть такая. Создаётся пост с параметрами title, description, images. Эти данные записывается в базу. После чего данные отображаются в виде постов. Проблема в том, что пост создается, но без картинки, хотя в базе она существует.

Ещё заметил, что в таблице images столбец post_id всегда создается пустым, хотя долен брать брать ID поста в котором был создан

введите сюда описание изображения

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title th:text="${title}"></title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
              integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    </head>
    <body>
    <header th:insert="blocks/header :: header"></header>
    
    <div class="album py-5 bg-body-tertiary">
        <div class="container mt-5">
            <div class="container mt-5">
                <div th:each="post : ${posts}" class="alert alert-info mt-2">
                    <img th:src="@{/images/post.images}" alt="img" class="img-thumbnail" height="80pxa"/>
                    <h3 th:text="${post.title}"/>
                    <p th:text="${post.description}"/>
                    <a th:href="'/post/' + ${post.id}" class="btn btn-warning">Детальнее</a>
                </div>
            </div>
            <div class="d-grid gap-2 d-md-block">
                <a href="/post/creat">
                    <br>
                    <button type="button" class="btn btn-primary">Добавить модель</button>
                </a>
            </div>
        </div>
    </div>

<footer th:insert="blocks/footer :: footer"></footer>
</body>
</html>

Класс: Image

package ru.monkeyTeam.demo.models;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Entity
@Table(name = "images")
@AllArgsConstructor
@NoArgsConstructor
public class Image {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long  id;
    @Column(name = "name")
    private String name;
    @Column(name = "size")
    private String  size;
    @Column(name = "originalFileName")
    private String originalFileName;
    @Column(name = "contentType")
    private String contentType;
    @Lob
    private byte[] bytes;
    @ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
    @JoinColumn(name = "post_id")
    private Post post;
}

Класс: Post

package ru.monkeyTeam.demo.models;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "posts")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Post {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(name = "title")
    private String title;
    @Column(name = "description", columnDefinition = "text")
    private String description;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "post", targetEntity  = Image.class)
    private List<Image> images = new ArrayList<>();
    private LocalDateTime dateTime;
    @PrePersist
    private void init() {
        dateTime = LocalDateTime.now();
    }
    public void addImageToPost(Image image) {
        images.add(image);
    }

}

Класс: PostService

package ru.monkeyTeam.demo.services;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.objenesis.SpringObjenesis;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.monkeyTeam.demo.models.Image;
import ru.monkeyTeam.demo.models.Post;
import ru.monkeyTeam.demo.repositories.PostRepository;

import java.io.IOException;

@Service
@Slf4j
@RequiredArgsConstructor
public class PostService {
    private final PostRepository postRepository;

    public Iterable<Post> listPost(String title) {
        if (title != null) {
            return postRepository.findByTitle(title);
        }
        return postRepository.findAll();
    }

    public void savePost(Post post, MultipartFile file) throws IOException {
        Image image = new Image();
        if (!file.isEmpty()) {
            image.setName(file.getName());
            image.setOriginalFileName(file.getOriginalFilename());
            image.setContentType(file.getContentType());
            image.setSize(String.valueOf(file.getSize()));
            image.setBytes(file.getBytes());
            post.addImageToPost(image);
        }
        log.info("Saving new Post. Title: {}" , post.getTitle());
        postRepository.save(post);
    }

    public void deletePost(Long id) {
        log.info("Delete post {}" , postRepository.findById(id));
        postRepository.deleteById(id);
    }

    public Post getPostById(Long id) {
        return postRepository.findById(id).orElse(null);
    }
}

Класс: PostController

package ru.monkeyTeam.demo.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ru.monkeyTeam.demo.models.Post;
import ru.monkeyTeam.demo.services.PostService;

import java.io.IOException;

@Controller
@RequiredArgsConstructor
public class PostController {

    private final PostService postService;

    @GetMapping("/")
    public String posts(@RequestParam(name = "title", required = false) String title,Model model) {
        model.addAttribute("posts", postService.listPost(title));
        return "posts";
    }

    @GetMapping("/post/creat")
    public String pageCreatPost(Model model) {
        return "post_creat";
    }

    @PostMapping("/post/creat")
//    @RequestMapping(value = "/post/creat", method = RequestMethod.POST)
    public String createPost(@RequestParam("file") MultipartFile file, Post post) throws IOException {
        postService.savePost(post, file);
        return "redirect:/";
    }

    @PostMapping("/post/delete/{id}")
    public String deletePost(@PathVariable Long id) {
        postService.deletePost(id);
        return "redirect:/";
    }

    @GetMapping("post/{id}")
    public String postInfo(@PathVariable Long id, Model model) {
        Post post = postService.getPostById(id);
        model.addAttribute("post", post);
        model.addAttribute("images", post.getImages());
        return "post_info";
    }
}

Класс: ImageController

package ru.monkeyTeam.demo.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import ru.monkeyTeam.demo.models.Image;
import ru.monkeyTeam.demo.repositories.ImageRepository;

import java.io.ByteArrayInputStream;

@RestController
@RequiredArgsConstructor
public class ImageController {
    private final ImageRepository imageRepository;
    @GetMapping("/images/{id}")
    private ResponseEntity<?> getImageById(@PathVariable Long id) {
        Image image = imageRepository.findById(id).orElse(null);
        return ResponseEntity.ok()
                .header("fileName", image.getOriginalFileName())
                .contentType(MediaType.valueOf(image.getContentType()))
                .contentLength(Long.parseLong(image.getSize()))
                .body(new InputStreamResource(new ByteArrayInputStream(image.getBytes())));
    }

}

Ответы

▲ 0Принят
  1. Для сохранения id постинга в картинке следует установить связь между этими сущностями в методе Post::addImageToPost:
// class Post
public void addImageToPost(Image image) {
    images.add(image);
    image.setPost(this);
}
  1. Вывод картинок при помощи такого тега невозможен:
<img th:src="@{/images/post.images}" alt="img" class="img-thumbnail" height="80pxa"/>

Здесь явно не хватает цикла по коллекции картинок данного поста, в атрибуте src должна быть ссылка на метод контроллера /images/{id}, где следует указать идентификатор картинки.