1

我目前正在尝试从表单(名称、密码、图像)等发送数据。我正在使用 Spring Boot、JPA、Thymeleaf 和 MultipartFile,但出现以下错误:

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

在在这里发布我的问题之前,我在谷歌上进行了搜索,但找不到任何可以帮助我的东西。起初,我认为 MultipartFile 有问题,但决定摆脱 BindingResult(我用它来显示我的 thymeleaf 模板中的错误,例如密码不匹配正则表达式或某些字段没有足够的字符等)和它解决了这个问题。图片已成功上传到数据库。

但是,我想保留 BindingResult 并使其与 MultipartFile 一起使用。

这是我的代码。

我的实体(配置):

@Entity
@Table(name = "config")
public class Config {

    @Id
    @GeneratedValue
    private int id;
    
    @NotNull
    @Size(min=4, max=50, message="le nom du restaurant doit contenir au moins 4 caractères")
    private String restaurantName;
    
    @NotNull
    private String url;
    
    @Pattern(regexp="^(?=.{8,}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$", flags = Flag.UNICODE_CASE, 
            message="Le mot de passe doit contenir au moins 8 caratères dont une majuscule, une minuscule et 1 chiffre")
    private String password;
    
    private String linkColor;
    private String menuColor;
    private String buttonColor;
    
    @Column(name = "header")
    private byte[] header;
    
    public String getRestaurantName() {
        return restaurantName;
    }
    public void setRestaurantName(String restaurantName) {
        this.restaurantName = restaurantName;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getLinkColor() {
        return linkColor;
    }
    public void setLinkColor(String linkColor) {
        this.linkColor = linkColor;
    }
    public String getMenuColor() {
        return menuColor;
    }
    public void setMenuColor(String menuColor) {
        this.menuColor = menuColor;
    }
    public String getButtonColor() {
        return buttonColor;
    }
    public void setButtonColor(String buttonColor) {
        this.buttonColor = buttonColor;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public byte[] getHeader() {
        return header;
    }
    public void setHeader(byte[] header) {
        this.header = header;
    }

}

我的配置服务:

@Service
public class ConfigService {

    @Autowired
    private ConfigRepository repo;
    
    public Config getConfigById(int id) {
        return repo.findById(id).orElse(null);
    }
    
    public Config getConfigByRestaurantName(String name) {
        return repo.findByRestaurantName(name);
    }
    
    public String deleteConfig(int id) {
        repo.deleteById(id);
        return "Config has been deleted!";
    }
    
    public long configAlreadyExist() {
        return repo.count();
    }
    
    public List<Config> getAll() {
        return repo.findAll();
    }
    
    public Config saveConfig(Config config) {
        return repo.save(config);
    }
    
}

配置控制器:

@PostMapping("/config/add")
    public String addConfig(@Valid @ModelAttribute("config") Config config, BindingResult bindingResult, @RequestParam(value="header", required=false) MultipartFile file) throws IOException {
        
        if(bindingResult.hasErrors()) {
            return "config";
        }
        else {
            config.setHeader(file.getBytes());
            service.saveConfig(config);
            return "redirect:/config/confirm";
        }
    }

我的表格(我正在使用百里香叶):

<form action="#" th:action="@{/config/add}" th:object="${config}" method="post" enctype="multipart/form-data">
          <div class="form-group">
            <label for="restaurant_name">Nom du restaurant</label>
            <input type="text" th:field="*{restaurantName}"/>
            <div th:if="${#fields.hasErrors('restaurantName')}" th:errors="*{restaurantName}" class="error">Restaurant Name error</div>
          </div>
          <div class="form-group">
            <label for="url">URL du site</label>
            <input type="text" class="form-control" id="url" th:field="*{url}">
          </div>
          <div class="form-group">
            <label for="link_color">Couleur pour les liens</label>
            <select class="form-control" th:field="*{linkColor}">
              <option value="blue">Bleu</option>
              <option value="red">Rouge</option>
              <option value="yellow">Jaune</option>
              <option value="green">Vert</option>
              <option value="grey">Gris</option>
            </select>
          </div>
          <div class="form-group">
            <label for="menu_color">Couleur pour les menus</label>
            <select class="form-control" th:field="*{menuColor}">
              <option value="blue">Bleu</option>
              <option value="red">Rouge</option>
              <option value="yellow">Jaune</option>
              <option value="green">Vert</option>
              <option value="grey">Gris</option>
            </select>
          </div>
          <div class="form-group">
            <label for="button_color">Couleur pour les boutons</label>
            <select class="form-control" th:field="*{buttonColor}">
              <option value="blue">Bleu</option>
              <option value="red">Rouge</option>
              <option value="yellow">Jaune</option>
              <option value="green">Vert</option>
              <option value="grey">Gris</option>
            </select>
          </div>
          <div class="form-group">
            <label for="password">Password</label>
            <input type="password" th:field="*{password}"/>
          </div>
          <div th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="error">Password error</div>
          <div class="form-group">
            <label for="header">Header file</label>
            <input type="file" class="form-control" id="header" th:field="*{header}">
            <div th:if="${#fields.hasErrors('header')}" th:errors="*{header}" class="error">Header error</div>
          </div>
          <button type="submit" class="btn btn-primary">Submit</button>
          <div>
            <p th:text="${error}" id="error"></p>
          </div>
        </form>

据我了解,在我的实体(配置)中,标头是一个字节 [](longblob),但由于 MultifilePart 以不同的格式处理我的文件,一个与我的实体中的字节 [] 不匹配的格式,这就是导致错误。

请问有什么简单的方法可以解决这个问题吗?

谢谢!

编辑:我通过使用 @InitBinder 找到了一个临时解决方法

@InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("header");
    }

我仍然很想知道是否有另一种方法来处理这个问题(不禁用该字段),所以我仍然可以检查文件是否为 png、jpg 等(以增加安全性)。

4

0 回答 0