【问题标题】:spring multipart file upload form validationspring多部分文件上传表单验证
【发布时间】:2012-04-10 11:51:06
【问题描述】:

我是 Spring 新手,目前我正在努力解决获得多部分表单提交/验证场景所需的许多部分,并在视图中显示错误蜂鸣。

这是我目前拥有的文件:

resourceupload.jsp :显示上传文件的表单的视图。

<form:form method="post" action="resource/upload" enctype="mutlipart/form-data">
 <input name="name" type="text"/>
 <input name="file" type="file" />
 <input type="submit"/>
<form:errors path="file" cssClass="errors"/>
</form>

resourceuploadcontroller.java :处理表单提交的控制器,并且(不成功)尝试将文件验证错误发布回视图:

@RequestMapping(method = RequestMethod.POST)
public String handleFormUpload( @RequestParam("file") MultipartFile file , @RequestParam("name") String name,Object command, Errors validationErrors){
..perform some stuff with the file content, checking things in the database, etc...
.. calling validationErrors.reject("file","the error") everytime something goes wrong...

return "redirect:upload"; // redirect to the form, that should display the error messages

现在,显然这种方法有问题:

1/ 我必须在validationErrors 参数之前添加一个虚拟的“命令”对象,否则spring 会给我一个错误。这似乎不太对。

2/ 添加该参数后,重定向不会将错误传递给视图。我尝试在控制器的开头使用@SessionAttribute("file"),但没有任何运气。

如果有人可以提供帮助...我已经查看了 @ResponseBody 注释,但这似乎不适用于视图..

【问题讨论】:

    标签: validation spring-mvc multipartform-data


    【解决方案1】:

    好像我自己找到了解决方案。

    首先,对我帮助很大的链接:http://www.ioncannon.net/programming/975/spring-3-file-upload-example/Spring 3 MVC - form:errors not showing the errors 这显示了一个很好的技巧来显示所有错误,使用

    <form:errors path="*"/>. 
    

    现在,我为使该功能正常工作而更改的所有内容的列表:

    1/ 使用“rejectValue”而不是“reject”。

    2/ 直接返回视图而不是重定向。

    3/ 创建一个带有 CommonsMultipartFile 属性的“UploadItem”模型

    所以,总而言之,我的控制器方法变成了

    @RequestMapping(method = RequestMethod.POST)
    public String handleFormUpload( @ModelAttribute("uploadItem") UploadItem uploadItem, BindingResult errors){
    ... use errors.rejectValue ... in case of errors (moving everything i could in a UploadItemValidator.validate function)
    return "uploadform"
    

    希望有所帮助。

    【讨论】:

      【解决方案2】:

      这是一个非常简单的方法:

      formBackingObject:

      import org.springframework.web.multipart.commons.CommonsMultipartFile;
      
      public class FileImport {
      
          CommonsMultipartFile  importFile;
      
          public CommonsMultipartFile getImportFile() {
              return importFile;
          }
      
          public void setImportFile(CommonsMultipartFile importFile) {
              this.importFile = importFile;
          }
      }
      

      形式:

      <sf:form method="POST" modelAttribute="fileImport" enctype="multipart/form-data" action="import">
          <table>
              <spring:hasBindErrors name="fileImport">
                  <tr>
                      <td colspan="2">
                          <sf:errors path="importFile" cssClass="error"/>
                      </td>
                  </tr>
              </spring:hasBindErrors>
              <tr>
                  <th><label for="importFile">Import Workload:</label></th>
                  <td><input name="importFile" type="file"></td>
              </tr>
          </table>
          <input type="submit" value="Import Application Data">
      </sf:form>
      

      最后是 ControllerClassMethod:

      @RequestMapping(value={"/import"}, method=RequestMethod.POST)
      public String importWorkload(
              FileImport fileImport, BindingResult bindResult,
              @RequestParam(value="importFile", required=true) MultipartFile importFile ){
          if( 0 == importFile.getSize() ){
              bindResult.rejectValue("importFile","fileImport.importFile");
          }
      
          if(bindResult.hasErrors()){
              return "admin";
          }
      ....
      }
      

      简单易懂!

      @NotNull 注释不适用于文件的原因是多部分文件在请求对象中永远不会为空。但是,它可以有 0 个字节。您可以花时间实现自定义验证器,但为什么呢?

      【讨论】:

        【解决方案3】:

        在 Spring 4 中,您可以像下面这样实现文件验证器:

        @Component
        public class FileValidator implements Validator {
        
            @Override
            public boolean supports(Class<?> clazz) {
                return FileModel.class.isAssignableFrom(clazz);
            }
        
            @Override
            public void validate(Object target, Errors errors) {
                FileModel fileModel = (FileModel) target;
        
                if (fileModel.getFile() != null && fileModel.getFile().isEmpty()){
                    errors.rejectValue("file", "file.empty");
                }
            }
        }
        

        然后将上面的验证器注入到上传控制器中,如下所示:

        @Controller
        @RequestMapping("/")
        public class FileUploadController {
        
            @Autowired
            private FileValidator fileValidator;
        
            @ModelAttribute
            public FileModel fileModel(){
                return new FileModel();
            }
        
            @InitBinder
            protected void initBinderFileModel(WebDataBinder binder) {
                binder.setValidator(fileValidator);
            }
        
            @RequestMapping(method = RequestMethod.GET)
            public String single(){
                return "index";
            }
        
            @RequestMapping(method = RequestMethod.POST)
            public String handleFormUpload(@Valid FileModel fileModel,
                                           BindingResult result,
                                           RedirectAttributes redirectMap) throws IOException {
        
                if (result.hasErrors()){
                    return "index";
                }
        
                MultipartFile file = fileModel.getFile();
                InputStream in = file.getInputStream();
                File destination = new File("/tmp/" + file.getOriginalFilename());
                FileUtils.copyInputStreamToFile(in, destination);
        
                redirectMap.addFlashAttribute("filename", file.getOriginalFilename());
                return "redirect:success";
            }
        }
        

        此实现有助于您的代码更清晰、更易读。我是从教程Spring MVC File Upload Validation Example找到的

        【讨论】:

          【解决方案4】:

          我不认为这种方法完全包含 spring,但它很有效,很简单,并且使用简单的 html 表单和控制器中的一个方法:

          发帖的html文件(另存为jsp或html,你自己调用)

          <html>
            <head>
              <title>File Upload Example</title>
            </head>
            <body>
              <form action="save_uploaded_file.html" method="post" enctype="multipart/form-data">
                  Choose a file to upload to the server:
                  <input name="myFile" type="file"/><br/>
                <p>
                  <input type="submit"/>
                  <input type="reset"/>
                </p>
              </form>
            </body>
          </html>
          

          在你的控制器中,有以下方法:

          @RequestMapping("/save_uploaded_file")
          public String testUpload(HttpServletRequest request) throws Exception
          {
              // get the file from the request
              MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
              MultipartFile multipartFile = multipartRequest.getFile("myFile");
          
              // Note: Make sure this output folder already exists!
              // The following saves the file to a folder on your hard drive.
              String outputFilename = "/tmp/uploaded_files/file2.txt";
              OutputStream out = new FileOutputStream(outputFilename);
              IOUtils.copy(multipartFile.getInputStream(), out);
          
              return "/save_uploaded_file";
          }
          

          要让更大的文件可以上传(超过 40k),您可能需要在 spring servlet 配置中指定以下内容....如果需要,可以在此处显示“真实”数字。

          <!-- Configure the multipart resolver -->
          <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
              <!-- one of the properties available; the maximum file size in bytes -->
              <property name="maxUploadSize" value="500000000"/>
              <property name="maxInMemorySize" value="500000000" />
          </bean>
          

          请注意,Spring 的文件上传内容在后台使用 Apache Commons FileUpload。您需要下载它并将其包含在您的应用程序中。这反过来也需要Apache Commons IO,所以你也需要它。 (引自here

          【讨论】:

            猜你喜欢
            • 2015-10-26
            • 1970-01-01
            • 2014-10-31
            • 2017-11-05
            • 1970-01-01
            • 1970-01-01
            • 2015-10-31
            • 1970-01-01
            • 2021-05-12
            相关资源
            最近更新 更多