스프링 프레임워크에서 다중 파일업로드 예
스프링에서 업로드를 위한 설정은 우측 링크를 눌러 참조하세요. 여기를 클릭하세요.
WEB-INF/views/upload/uploadForm.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>파일 업로드 폼</title> </head> <body> <form:form method="post" enctype="multipart/form-data" modelAttribute="uploadVO" action="fileUpload"> 파일에 대한 설명: <form:input path="desc" type="text"/><br> 업로드할 파일 선택: <%--uploadVO객체 안에 files 변수가 존재해야 한다 --%> <form:errors path="files" style="color:red;"/><br> <input name="files[0]" type="file"/> <input name="files[1]" type="file"/><br> <input name="files[2]" type="file"/><br> <button type="submit">전 송</button><br> </form:form> </body> </html>
UploadController.java
package org.dodream.java; import java.io.*; import java.util.List; import javax.servlet.http.*; import org.dodream.model.UploadVO; import org.dodream.service.FileValidator; import org.springframework.beans.factory.annotation.*; import org.springframework.stereotype.*; import org.springframework.validation.*; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.*; import org.springframework.web.servlet.*; @Controller public class UploadController { @Autowired private FileValidator fileValidator; @RequestMapping(value="/upload/form", method=RequestMethod.GET) public String getUploadForm ( @ModelAttribute("uploadVO") UploadVO uploadVO ) { /*위에서 지정한 uploadVO 키는 폼이 처음 화면에 보일 때 폼의 각 필드가 request 영역에 저장된 UploadVO와 연결되어 오류가 발생하는 것을 막기 위한 것으로 POST 방식 요청을 처리하는 아래의 메소드와는 무관하다 */ return "upload/uploadForm"; } /*@ModelAttribute("uploadVO") UploadVO uploadVO 는 브라우저에서 전송되는 파라미터를 Model 객체에 uploadVO 라는 이름으로 저장한다는 것을 의미한다. Model 에 저장된 데이터는 내부에서 request 객체에 저장되므로 뷰에서 접근할 수 있게 된다 */ @RequestMapping(value="/upload/fileUpload", method=RequestMethod.POST) public ModelAndView fileUploaded( @ModelAttribute("uploadVO") UploadVO uploadVO, BindingResult result) { fileValidator.validate(uploadVO, result); if (result.hasErrors()) { return new ModelAndView("upload/uploadForm"); } // 업로드된 파일을 지정된 경로로 이동한다 List<MultipartFile> list = uploadVO.getFiles(); System.out.println("파일의 갯수:"+list.size()); InputStream inputStream = null; OutputStream outputStream = null; //다수개의 파일을 업로드하는 경우 처리하는 예 for(int i=list.size()-1;i>=0;i--) { MultipartFile file = list.get(i); // 파일의 내용이 비어 있는 경우에는 리스트에서 삭제한다 if(file.getSize()==0) { list.remove(i); continue; } String fileName = file.getOriginalFilename(); try { inputStream = file.getInputStream(); File newFile = new File("D:/upload/" + fileName); if (!newFile.exists()) { newFile.createNewFile(); } outputStream = new FileOutputStream(newFile); int read = 0; byte[] bytes = new byte[1024]; while ((read = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, read); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(inputStream!=null) inputStream.close(); if(outputStream!=null) outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return new ModelAndView("upload/uploadResult"); } @RequestMapping("/upload/download") @ResponseBody public byte[] getImage(HttpServletResponse response, @RequestParam String filename) throws IOException { File file = new File("D:/upload/"+filename); byte[] bytes = org.springframework.util.FileCopyUtils.copyToByteArray(file); //한글은 http 헤더에 사용할 수 없기때문에 파일명은 영문으로 인코딩하여 헤더에 적용한다 String fn = new String(file.getName().getBytes(), "iso_8859_1"); response.setHeader("Content-Disposition", "attachment; filename=\"" + fn + "\""); response.setContentLength(bytes.length); response.setContentType("image/jpeg"); return bytes; } }
UploadVO.java
package org.dodream.model; import java.util.List; import org.springframework.web.multipart.MultipartFile; public class UploadVO { private String desc; private List<MultipartFile> files; // 위의 files변수에 파일정보를 전달하기 위해서는 폼에서 다음과 같이 해야한다 // <input type="file" name="files[0]"> // <input type="file" name="files[1]"> public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public List<MultipartFile> getFiles() { return files; } public void setFiles(List<MultipartFile> files) { this.files = files; } }
FileValidator.java
package org.dodream.service; import java.util.List; import org.dodream.model.UploadVO; import org.springframework.stereotype.*; import org.springframework.validation.Errors; import org.springframework.validation.Validator; import org.springframework.web.multipart.MultipartFile; @Service("fileValidator") public class FileValidator implements Validator { public boolean supports(Class<?> arg0) { return false; } public void validate(Object obj, Errors errors) { UploadVO vo = (UploadVO) obj; List<MultipartFile> list = vo.getFiles(); boolean valid = false; //한개의 파일이라도 업로드된 경우에는 유효성검사에 통과한 것으로 한다 for(int i=0;i<list.size();i++){ if(list.get(i).getSize()!=0){ valid = true; }; } if(!valid){ errors.rejectValue("files", "UploadForm.SelectFile", "한개의 파일은 꼭 선택해야 합니다!"); // 메시지 리소스 파일을 사용하는 경우에는 UploadForm.SelectFile.files 키에 // 등록된 오류 메시지가 우선적으로 사용되고 그렇지 않으면 위에서 처럼 디폴트 메시지로 지정된 // 오류 메시지가 뷰로 전달된다. 뷰에서는 spring 태그를 사용하여 // <form:errors path="files"/> } } }
WEB-INF/views/upload/uploadResult.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>파일 업로드 결과</title> <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script> <script type="text/javascript"> function download(fname){ $("#filename").val(fname); $("#downloadForm").submit(); } </script> </head> <body> <h2>업로드된 파일 정보</h2> <c:forEach var="f" items="${requestScope.uploadVO.files}"> 파일명 : ${f.originalFilename} <a href="javascript:download('${f.originalFilename}');">다운로드</a> <br> </c:forEach> <form id="downloadForm" action="download" method="post"> <input type="hidden" id="filename" name="filename"> </form> </body> </html>