파일은 게시판에서 빠질 수 없는 필수적인 요소이다. 게시판의 글에 이미지파일을 첨부하는 경우도 있고, 다른 파일을 첨부하기도 한다. 그리고 그 파일을 다운받기도 한다.
파일형태의 데이터를 브라우저에서 어떻게 전달하고, 컨트롤러에서는 어떻게 처리해야하는가? 또한, 데이터베이스에는 파일 자체를 저장해야하는가?
반대로 브라우저에서 서버에 있는 파일을 다운받기 위해서는 어떻게 해야하는가?
form태그의 속성에 enctype 설정
<form name="input" method="post" action="write.do" enctype="multipart/form-data">
<input type="text" name="subject" size="60">
<input type='file' name='files'>
<input type='file' name='files'>
</form>
필요한 라이브러리 등록(commons-io, commons-fileuploads)(pom.xml)
<!-- commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
MultipartFile 구현클래스 객체를 만들어준다.(servlet-context.xml)
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="defaultEncoding" value="UTF-8" />
<beans:property name="maxUploadSize" value="10485760" />
<beans:property name="maxUploadSizePerFile" value="2097152"/>
<beans:property name="maxInMemorySize" value="10485756"/>
</beans:bean>
컨트롤러에서 MultipartFile 인터페이스를 사용한다.
@PostMapping("write.do")
public String write(Board board, @RequestParam ArrayList<MultipartFile> files) {
service.write(board, files);
return "redirect:list.do";
}
AbstractView 를 상속하는 클래스를 작성한다.
public class FileDownloadView extends AbstractView { // View역할을 하는 JSP같은 것이다.
public FileDownloadView() {
setContentType("application/download;charset=utf-8");
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
File file = (File)model.get("downloadFile");
response.setContentType(getContentType());
response.setContentLength((int)file.length());
String value = "attachment; filename="+ java.net.URLEncoder.encode(file.getName(), "utf-8") +";";
response.setHeader("Content-Disposition", value);
response.setHeader("Content-Transfer-Encoding", "binary");
OutputStream os = response.getOutputStream();
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
FileCopyUtils.copy(fis, os);
os.flush();
}catch(IOException ie) {
log.info("FileDownloadView ie: " + ie);
}finally {
if(fis != null) fis.close();
if(os != null) os.close();
}
}
}
클래스의 객체를 servlet-context.xml에서 생성해준다.
<!-- 파일 다운로드 -->
<beans:bean id="fileDownloadView" class="sdo.md.filesetting.FileDownloadView" />
<beans:bean id="fileViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
<beans:property name="order" value="0" />
</beans:bean>
처음에 생성해준 객체의 아이디가 뷰의 이름이 된다.(fileDownloadView >> fileDownloadView.jsp) 컨트롤러에서 호출해줌.
@GetMapping("download.do")
public ModelAndView download(@RequestParam String fname) {
File file = new File(Path.FILE_STORE, fname);
if(file.exists()) {
return new ModelAndView("fileDownloadView","downloadFile", file);
}else {
return new ModelAndView("redirect:list.do");
}
}