Spring validation of multi-page file upload form

I am new to spring and am currently struggling with many of the parts needed to get a submit / check multiple form script with the error displayed in the view.

Here are the files that I have:

resourceupload.jsp: view showing the form for uploading a file.

<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: a controller that processes the submit form, and (unsuccessfully) tries to send file validation errors back to the view:

 @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 

Now, obviously, something is wrong with this approach:

1 / I had to add a dummy "command" object before the validationErrors parameter, otherwise spring will throw an error. This does not seem really correct.

2 / After I added this parameter, the redirection does not pass errors to the view. I tried using @SessionAttribute ("file") at the beginning of the controller, with no luck.

If anyone can help ... I looked at the @ResponseBody annotation, but this does not seem to be used for use with views.

+4
source share
4 answers

I seem to have found a solution myself.

Firstly, the link that helped me a lot: http://www.ioncannon.net/programming/975/spring-3-file-upload-example/ and also Spring 3 MVC - form: errors that do not display errors that showed good trick to display all errors using

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

Now a list of all the things that I changed to make this thing work:

1 / use "rejectValue" instead of "reject".

2 / return the view directly instead of redirecting.

3 / create the "UploadItem" model with the CommonsMultipartFile property

So overall my management method has become

 @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" 

Hope this helps.

+3
source

Here is a very simple way to do this:

Form 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; } } 

The form:

 <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> 

And finally, 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"; } .... } 

Easy Peasy!

The reason the @NotNull annotation does not work for files is because a multidisc file is never null in the request object. But it can have 0 bytes. You can spend time doing a custom validator, but why?

+2
source

I don't think this approach fully covers spring, but it works, is simple and uses a simple html form and one method in the controller:

html file to record (save as jsp or html, your call)

 <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> 

in your controller, follow these steps:

 @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"; } 

To get larger files to download (over 40k), you may need to specify the following spring servlet configuration. I put a few large files there to make sure this works, but of course the "real" numbers are there if you need to.

 <!-- 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> 

Note that spring file upload uses Apache Commons FileUpload under covers. You need to download it and include it in your application. This, in turn, also requires Apache Commons IO , so you will need it too. (quote from here )

+1
source

In Spring 4, you can implement a file validation tool as shown below:

 @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"); } } } 

Then add the validator above to the load controller, for example below:

 @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"; } } 

This implementation helps your code become more understandable and understandable. I found this from a Spring tutorial . MVC file upload verification example

+1
source

Source: https://habr.com/ru/post/1403562/


All Articles