【问题标题】:Spring MultipartFile causing form validation to not be mappedSpring MultipartFile 导致表单验证未映射
【发布时间】:2017-11-24 20:25:23
【问题描述】:

首先我要说我对 Spring 的了解非常有限。但是,我已经能够解决过去遇到的问题。我的最新问题对我来说没有多大意义。

所以我得到的是一个表格,它包含要在拍卖中出售的物品的属性。此表单有一个可选字段,可以上传所售商品的图片。图像上传按原样工作。我注意到我的表单实际上并没有显示验证期间给出的错误,所以我开始研究可能导致这种情况的原因。如果我从方法签名中删除 MultipartFile,Web 将正确显示表单验证错误(如果存在)。但是,现在我没有我需要的图像。

另一方面,如果我将 required = false 属性添加到 MultipartFile 上的 RequestParam,我的问题仍然存在,并且当表单不符合验证集时,我会遇到 following

如果项目有效或显示验证错误,该方法应该保存项目的 Java 端如下:

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView save(@Valid Item item, @RequestParam(name = "itemImage", required = false) MultipartFile file,
                         BindingResult result, RedirectAttributes redirect) {
    if (result.hasErrors()) {
        return new ModelAndView("item/save", "formErrors", result.getAllErrors());
    }

    boolean isCreate = (null == item.getId());

    if (file != null && !file.isEmpty()) {
        if (isCreate) {
            item = itemService.save(item);
        }

        Path directory = Paths.get(itemImageDir + "/" + item.getAuction().getId() + "/" + item.getId());

        if (!Files.exists(directory)) {
            try {
                Files.createDirectories(directory);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            Files.copy(file.getInputStream(), Paths.get(directory.toString(), file.getOriginalFilename()),
                    StandardCopyOption.REPLACE_EXISTING);
            item.setImageUrl(String.format("/items/image/%s/%s/%s", item.getAuction().getId(), item.getId(), file
                    .getOriginalFilename()));
            itemService.save(item);
        } catch (IOException | RuntimeException e) {
            result.addError(new ObjectError("imageUrl", "Failed to upload " + file.getOriginalFilename() + " => "
                    + e.getMessage()));
            return new ModelAndView("item/save", "formErrors", result.getAllErrors());
        }
    } else {
        itemService.save(item);
    }

    String message = "Successfully created a new item.";
    if (!isCreate)
        message = "Item has been successfully updated.";

    redirect.addFlashAttribute("globalMessage", message);
    return new ModelAndView("redirect:/auctions/{item.auction.id}", "item.auction.id", item.getAuction().getId());
}

这个页面的视图,没有多余的绒毛,看起来像这样:

<form id="auctionForm" class="col-xs-12" th:action="@{/items/(item)}" th:object="${item}"
      action="#" method="post" enctype="multipart/form-data">
    <div th:class="'form-group row'">
        <label for="itemImage" class="control-label col-sm-2"> Image Upload: </label>
        <div class="col-sm-4">
            <input id="itemImage" type="file" name="itemImage"/>
        </div>
    </div>
</form>

问题的额外上下文:如果我删除 @Valid 注释,该方法将被调用并且不会在表单无效时失败。但是,当我有@Valid 时,甚至没有命中控制器方法。如果它没有到达控制器,有没有办法检查它在哪里失败?我将这个控制器与所有其他控制器进行了比较,它似乎遵循相同的模式。

如果有人有任何建议,我将不胜感激。我真的不知道我错过了什么,所以欢迎提出任何建议。

【问题讨论】:

    标签: spring spring-mvc gradle spring-boot thymeleaf


    【解决方案1】:

    在控制器方法中添加 sigMultipartHttpServletRequest mrequest 并检查一次

    【讨论】:

    • 您是建议我向当前控制器添加一个 MultipartHttpServletRequest,还是使用此参数创建一个新方法?我在该对象内部检查什么?
    【解决方案2】:

    好的,所以我知道我错过了什么。作为 Spring 新手,我没有意识到参数顺序可能很重要。显然 BindingResult 必须立即跟随您要验证的参数。因此,我将方法签名更改为以下内容,现在一切都按预期工作:

        public ModelAndView save(@Valid Item item, BindingResult result, @RequestParam(name = "itemImage", required = false) MultipartFile file,
                         RedirectAttributes redirect) {
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      • 2014-04-18
      • 2012-12-25
      • 1970-01-01
      • 1970-01-01
      • 2020-05-07
      相关资源
      最近更新 更多