Хранить картинки в базе данных H2 весенняя загрузка thymleaf - PullRequest
0 голосов
/ 31 августа 2018

Добрый день. Я хочу сохранить изображение в базе данных h2, а затем извлечь и отобразить это изображение на html-странице. Я использую метод весенней загрузки и загрузки файлов, но получаю ошибки в результатах привязки

Вот страницы / классы:

Category.java

package com.vishal.project.entities;

@Entity
@Table(name="category")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="ID")
private Long id;

@Size(min=1, max=90)
@Column(name="CATEGORY_NAME")
private String CategoryName;


@Lob
@Column(name="CATEGORY_PHOTO")
private byte[] CategoryPhoto;


public Category(Long id, @Size(min = 1, max = 90) String categoryName, byte[] categoryPhoto) {
    super();
    this.id = id;
    CategoryName = categoryName;
    CategoryPhoto = categoryPhoto;
}

public byte[] getCategoryPhoto() {
    return CategoryPhoto;
}

public void setCategoryPhoto(byte[] categoryPhoto) {
    CategoryPhoto = categoryPhoto;
}

public Category() {}

@OneToMany(mappedBy = "category", cascade=CascadeType.ALL, orphanRemoval=true)
private Set<Book> Books = new HashSet<>();

public Set<Book> getBooks() {
    return Books;
}

public void setBooks(Set<Book> books) {
    Books = books;
}

public Long getId() {
    return id;
}
public void setCategoryID(Long id) {
    this.id = id;
}
public String getCategoryName() {
    return CategoryName;
}
public void setCategoryName(String categoryName) {
    CategoryName = categoryName;
}

@Override
public String toString() {

    return "Category ID:" + id + 
           "Category Name:"+ CategoryName;
}


}

Categorycontroller.java

package com.vishal.project.web;


import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.vishal.project.entities.Category;
import com.vishal.project.services.CategoryService;
import com.vishal.project.util.Message;


@Controller
@RequestMapping(value="/categories")
public class CategoryController {


private final Logger logger = LoggerFactory.getLogger(BookController.class);

@Autowired
private MessageSource  messageSource;

@Autowired 
private CategoryService categoryService;

@GetMapping
public String list(Model uiModel) {
    logger.info("Listing categories:");
    List<Category> categories = categoryService.findALL();
    uiModel.addAttribute("categories", categories);
    logger.info("No. of categories: " + categories.size());
    return "categories";
}

@GetMapping(value = "/{id}" , consumes="Multipart/formdata")
public String show(@PathVariable Long id, Model model) {
    Category category = categoryService.findbyID(id);


    model.addAttribute("category", category);
    return "showCategory";
}

@GetMapping(value = "/edit/{id}")
public String updateForm(@PathVariable Long id, Model model) {
    model.addAttribute("category", categoryService.findbyID(id));
    return "updateCategory";
}

@GetMapping(value = "/new")
public String create(Model uiModel) {
    logger.info("creating Category ...");
    Category category = new Category();     

    uiModel.addAttribute("category", category);
    return "updateCategory";
}


@PostMapping(value = "/upload")
public String saveCategory(@Valid @ModelAttribute("category") Category category, BindingResult bindingResult,
        Model uiModel, HttpServletRequest httpServletRequest, RedirectAttributes redirectAttributes,
        Locale locale, @RequestParam(value="file", required=true) MultipartFile file) {
    logger.info("Creating Category....");
    logger.info("Category ID" + category.getId());
    logger.info("Category ID" + category.getCategoryName());
    logger.info("Category ID" + category.getCategoryPhoto());
    if(bindingResult.hasErrors())
    {
        logger.info("Error:", bindingResult.getAllErrors());
        logger.debug("field Error:", bindingResult.getFieldError());
        uiModel.addAttribute("message", new Message("error", messageSource.getMessage("category_save_fail", new Object[] {}, locale)));
        uiModel.addAttribute("category", category);
        return "updateCategory";
    }
    uiModel.asMap().clear();
    redirectAttributes.addFlashAttribute("message", 
            new Message("success", messageSource.getMessage("Category_save_success", new Object[] {}, locale)));
    //process upload file 
    logger.info("File Name :", file.getName() );
    logger.info("File Size :", file.getSize() );
    logger.info("File content type :", file.getContentType() );
    if(file != null) {
    byte[] filecontent = null;
    try
    {
        InputStream inputStream = file.getInputStream();
        if(inputStream == null) 
            logger.debug("file InputStream is null");
        filecontent = IOUtils.toByteArray(inputStream);     
        category.setCategoryPhoto(filecontent);
    }catch(IOException ex) {
        logger.error("Error Saving uploaded file");
    }
    category.setCategoryPhoto(filecontent);
    }

    categoryService.save(category);
    return "redirect:/categories/" + category.getId().toString();
}

}

category Image

categoryShow.page

<body>
<div th:replace="fragments/header_admin :: header_admin">Header</div>
<div class="container">

<h1>Category Details</h1>

<div>
    <form class="form-horizontal" th:object="${category}" >
    <input type="hidden" th:field="*{id}"/>
        <div class="form-group">
            <label class="col-sm-2 control-label">Category Name:</label>
            <div class="col-sm-10">
                <p class="form-control-static" th:text="${CategoryName}"> 
</p></div>
        </div>

        <div class="form-group">
            <label class="col-sm-2 control-label" >Category Photo</label>
            <div class="col-sm-10">
                <p class="form-control-static" ><img alt="CatName" 
  th:src="@{CategoryPhoto}" /> </p></div>
        </div>
    </form>
</div>

CategoryUpdate page (создание или обновление категории с подробностями и изображением)

<div class="container">

<h1>Category Details</h1>

<div>
    <form  class="form-horizontal" th:object="${category}" th:action="@{/categories/upload}" method="post" enctype="multipart/form-data">
        <input type="hidden" th:field="*{id}"/>
        <div class="form-group">
            <label class="col-sm-2 control-label">Category Name</label>
            <div class="col-sm-10">
                <input class="form-control" th:field="*{CategoryName}"/>
            </div>
        </div>
          <div class="form-group">
            <label class="col-sm-2 control-label">Category Photo</label>
            <div class="col-sm-10">
                <input name="file" type="file" class="form-control" th:field="*{CategoryPhoto}"/>
            </div>
        </div>
        <div class="row">
            <button class="btn btn-default">Save</button>
        </div>
    </form>
</div>
<div th:insert="~{fragments/footer :: footer}">&copy; 2017 Iuliana Cosmina & Apress</div>

Ошибка: я получаю в bindingResult метода CategoryController.saveCategory ().

Когда я отлаживаю код, я получаю сообщение об ошибке. Вот картинка для демонстрации:

enter image description here

Мне трудно показывать изображения на странице CategoryShow с помощью thymleaf. Любая помощь будет оценена.

Обновление: Может кто-нибудь сказать мне, что означает эта ошибка, пожалуйста:

Failed to convert property value of    type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'byte[]' for property 'CategoryPhoto'; nested exception is 
java.lang.IllegalArgumentException: Cannot convert value of type 'org.springframework.web.multipart.support.
StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'byte' for property
'CategoryPhoto[0]': PropertyEditor [org.springframework.beans.propertyeditors.CustomNumberEditor] returned 
inappropriate value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' 

** Окончательное обновление: я получаю эту ошибку: ** Необходимая часть запроса 'file' отсутствует

Ответы [ 4 ]

0 голосов
/ 10 сентября 2018

Проблемы решены. Просто скажите, что я сделал в моем случае:

1) Если вы загружаете один файл на странице, используйте файл детали в качестве аргумента для вашего сообщения. Отображение в методе контроллера

2) В моем втором выпуске изображение не отображалось на html-странице с использованием thymeleaf, потому что я использую byte [] для сохранения в моей базе данных. Так что это не было решено тимелистом. Поэтому я использовал Apache двоичный кодек Base64 (может быть добавлен как зависимость Gradle или Maven), чтобы преобразовать мое изображение byte [] в строку Base64, чтобы оно могло быть разрешено с помощью thymleaf. как это:

    Category category = categoryService.findbyID(id);
    byte[] image = category.getCategoryPhoto();
    String CatImage =  Base64.encodeBase64String(image);

затем в HTML

<img  th:src="@{'data:image/jpeg;base64,'+${Cimage}}" />

надеюсь, это кому-нибудь поможет !! спасибо.

0 голосов
/ 07 сентября 2018

Spring переводит загруженные файлы как MultipartFile объекты, поэтому вы не можете отобразить его напрямую в массив байтов.

Вы можете получить массив байтов из MultipartFile, используя MultipartFile # getBytes () .

В вашем случае вы можете использовать промежуточный объект (например, CategoryForm), где поле CategoryPhoto будет иметь тип MultipartFile. Затем в вашем контроллере вы отображаете его на объект Category, который у вас уже есть, используя метод, который я показал выше.

0 голосов
/ 07 сентября 2018

Привет, ваша форма Thymeleaf разрешается следующим образом: атрибут name удаляется, если присутствует атрибут th: field

<form class="form-horizontal" action="/categories/upload" method="post" enctype="multipart/form-data">
    <input id="id" name="id" value="" type="hidden">
    <div class="form-group">
        <label class="col-sm-2 control-label">Category Name</label>
        <div class="col-sm-10">
            <input class="form-control" id="CategoryName" name="CategoryName" value="">
        </div>
    </div>
      <div class="form-group">
        <label class="col-sm-2 control-label">Category Photo</label>
        <div class="col-sm-10">
            <input name="CategoryPhoto" class="form-control" id="CategoryPhoto" type="file">
        </div>
    </div>
    <div class="row">
        <button class="btn btn-default">Save</button>
    </div>
</form>

В котором четко указана ошибка, которую вы получаете, даже если вы упомянули как имя = "файл" при вводе файла, она разрешена в name = categoryPhoto из-за th: field = "* {CategoryPhoto}", упомянутого после тега name.

используйте th: value = "$ {product.name}" th: name = "name" th: id = "name" вместо th: field это будет более гибким

0 голосов
/ 04 сентября 2018

Что вы всегда можете сделать, это сравнить загруженный рабочий файл пример с вашим.

Еще одна вещь, которая будет полезна для сравнения ваших входных имен с именем метода вашего контроллера, ожидающего вашего файла.

Если ваш опубликованный код все еще актуален, вы можете найти имя «Fileimport» в файле, введенном в шаблон, но в вашем контроллере вы ожидаете файл (@RequestParam (value = "file", required = false)).

Другие вещи, которые помогут вам в отладке:

  • с помощью инструментов разработчика браузера и посмотрите, что вы отправляете через сеть
  • log входящих запросов на стороне сервера (либо таким образом, либо это слишком сложно для вас, вы можете просто перебирать имена параметров и регистрировать их (и, если возможно, их значения)

Если это не помогло вам, тогда, пожалуйста, обновите пост: обновите ваш код (шаблон + контроллер, если он был изменен) и дайте лучше использовать трассировку стека: лучше, я имею в виду, вы должны показывать не только последнюю N строку stacktrace, но, по крайней мере, до первой строки, где выполнение проходит через ваш код (другими словами, имя класса начинается с вашего пакета), даже лучше, если там есть первое значение Caused by или второе, если оно имеет смысл).

...