Spring MVC — загрузка файла с валидацией
В прошлой заметке был описан базовый пример загрузки файла с помощью Spring MVC. Здесь будет рассмотрен вариант загрузки файла с реализацией валидации и паттерна Post-Redirect-Get.
В начале короткий код представления:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <%@ page contentType="text/html;charset=UTF-8" language="java" 	pageEncoding="UTF-8"%> 	<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <html> <head> <title>Title</title> </head> <body> 	<form:form method="post" enctype="multipart/form-data" modelAttribute="uploadedFile" action="uploadFile"> //все атрибуты обязательные 		<table> 			<tr> 				<td>Upload File:</td> 				<td><input type="file" name="file" /></td> 				<td style="color: red; font-style: italic;"> 				<form:errors path="file" /></td> 			</tr> 			<tr> 				<td></td> 				<td><input type="submit" value="Upload" /></td> 				<td></td> 			</tr> 		</table> 	</form:form> </body> </html> | 
Теперь контроллер:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | @Controller @SessionAttributes("filename") public class FileController { 	@Autowired 	private FileValidator fileValidator; //автосвязывание с бином FileValidator 	private static final Logger logger = LoggerFactory.getLogger(FileController.class); 	@RequestMapping(value = "/uploadFile", method = RequestMethod.POST) 	@ResponseBody 	public ModelAndView uploadFile(@ModelAttribute("uploadedFile") UploadedFile uploadedFile, BindingResult result) {// имена параметров (тут - "uploadedFile") - из формы JSP. 		ModelAndView modelAndView = new ModelAndView(); 		String fileName = null; 		MultipartFile file = uploadedFile.getFile(); 		fileValidator.validate(uploadedFile, result); 		if (result.hasErrors()) { 			modelAndView.setViewName("main"); 		} else { 			try { 				byte[] bytes = file.getBytes(); 				fileName = file.getOriginalFilename(); 				String rootPath = "C:\\path\\" 				File dir = new File(rootPath + File.separator + "loadFiles"); 				if (!dir.exists()) { 					dir.mkdirs(); 				} 				File loadFile = new File(dir.getAbsolutePath() + File.separator + fileName); 				BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(loadFile)); 				stream.write(bytes); 				stream.flush(); 				stream.close(); 				logger.info("uploaded: " + loadFile.getAbsolutePath()); 				RedirectView redirectView = new RedirectView("fileuploaded"); 				redirectView.setStatusCode(HttpStatus.FOUND); 				modelAndView.setView(redirectView); 				modelAndView.addObject("filename", fileName); 			} catch (IOException e) { 				// TODO Auto-generated catch block 				e.printStackTrace(); 			} 		} 		return modelAndView; 	} 	@RequestMapping(value = "/fileuploaded", method = RequestMethod.GET) 	public String fileUploaded() { 		return "fileuploaded"; 	} } | 
Валидация:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Component public class FileValidator implements Validator { 	@Override 	public void validate(Object uploadedFile, Errors errors) { 		UploadedFile file = (UploadedFile) uploadedFile; 		if (file.getFile().getSize() == 0) { 			errors.rejectValue("file", "uploadForm.selectFile", "Please select a file!"); 		} 	} 	@Override 	public boolean supports(Class<?> clazz) { 		// TODO Auto-generated method stub 		return false; 	} } | 
Здесь используется собственный класс UploadedFile — обертка для MulipartFile:
| 1 2 3 4 5 6 7 8 9 10 11 12 | public class UploadedFile { 	private MultipartFile file; 	public MultipartFile getFile() { 		return file; 	} 	public void setFile(MultipartFile file) { 		this.file = file; 	} } | 
Как это всё работает?
Создана простая форма spring-mvc form:form method="post" enctype="multipart/form-data" modelAttribute="uploadedFile" action="uploadFile" и кнопка для выбора\загрузки файла. Данные отправятся в контроллер в метод ModelAndView uploadFile(@ModelAttribute("uploadedFile") UploadedFile uploadedFile, BindingResult result) .
Здесь получаем MultipartFile из uploadedFile, а так же выполняем метод validate(). В FileValidator идет проверка на 0 размер файла и выдается ошибка с помощью метода rejectValue(). Если ошибка возникла, то переходим на страницу «main», где отображается текст ошибки. В случае нормальной загрузки файла используется редирект с статусом FOUND и перенаправляется на страницу «fileuploaded» уже с методом GET (метод String fileUploaded() ) при этом добавляя объект в сессию(см. аннотацию SessionAtribute в контроллере).


