- Outsider's Dev Story
- 흔한 개발자의 개발 노트
- 내 아이큐 80, 너도 80, 둘이 합쳐 160 - 내…
- 조대협의 블로그
- 자바캔(Java Can Do IT) / 최범균 님
- Sangon, Han – 개발자; 읽고 생각하고 쓰고 …
- The Evolution of the Web
- NAVER D2
- Dashboard - SLiPP
- ITWorld Korea - 테크놀로지 리더를 위한 글…
- OKKY - All That Developer
- 웹Frameworks
- 오픈튜토리얼스
- 위키독스 / 온라인 책 제작 공유 플랫폼 서비스
- 블로터
- IT OnAir
- 한 처음에 / 백창92
- Divide my knowledge / 완프최
- SERI.org
Bigfat
[모델2] Multipart를 이용한 단일 파일 업로드 구현하기 (게시판 구현) 본문
Multipart를 이용해 단일 파일 업로드(Single File Upload)를 구현해보자
서블릿 3.0 스펙부터 파일 업로드(upload) 기능을 지원한다.
web.xml을 열어 파일을 업로드할 디렉토리의 경로를 컨텍스트 파라미터로 설정해준다. D드라이브 아래에 upload 폴더와 temp 폴더를 미리 만들어두자.
1 2 3 4 | <context-param> <param-name>saveDirectory</param-name> <param-value>D:\upload\</param-value><!-- 파일명을 바로 붙이기 위해 \까지 넣어주자 --> </context-param> | cs |
서블릿이 multipart를 인식하기 위해서 multipart-config를 설정해준다. 서블릿 3.0부터는 web.xml 없는 개발 및 배포가 가능하므로 @MultipartConfig 어노테이션으로 fileSizeThreshold, location, maxFileSize, maxRequestSize 속성을 설정할 수 있다(참고1).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <servlet> <servlet-name>bbsServlet</servlet-name> <servlet-class>com.edu.bbs.BBSServlet</servlet-class> <init-param> <param-name>bbsProperties</param-name> <param-value>D:\Dev\education\bbs\WebContent\bbs.properties</param-value> </init-param> <!-- multipart 설정 추가 --> <multipart-config> <location>D:\temp</location> <max-file-size>-1</max-file-size> <max-request-size>-1</max-request-size> <file-size-threshold>1024</file-size-threshold> </multipart-config> </servlet> | cs |
파일 업로드가 필요한 화면(*.jsp)의 form 태그에 enctype 속성을 multipart/form-data로, form 태그 내에 input 태그의 type을 file로 지정해준다. multipart는 HTTP POST로만 전송해야 한다(참고2).
1 2 3 4 5 | <form action="/bbs/write.bbs" method="post" enctype="multipart/form-data"> ... <input type="file" class="btn btn-default" name="file"> ... </form> | cs |
톰캣을 실행시키고 글쓰기 버튼을 누르면, 즉 write.bbs를 요청했을 때 Content-Type이 multipart/form-data로 되어있고, 데이터가 Request Payload로 넘어가는 것을 확인할 수 있다.
form 태그에 enctype 속성을 작성하지 않으면 default는 enctype="application/x-www-form-urlencoded"다. 아직 수정하지 않은 글 수정 기능으로 update.bbs 요청의 Request Headers와 Form Data를 확인할 수 있다.
write.bbs 요청에 대한 WriteImpl 클래스를 아래와 같이 작성한다. multipart 데이터는 request.getPart 메서드나 getParts 메서드를 이용해 받는다. multipart로 넘겨줬을 때 서블릿 3.0 규약에 따르면 Stream으로 데이터를 받아와야 하지만 파일을 제외한 form-data는 request.getParameter 메서드로 받아와도 문제는 없다.
getFileName 메서드는 Request Payload에서 filename의 값인 파일명을 뽑아내기 위한 메서드다.
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 67 68 69 70 | package com.edu.bbs; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; public class WriteImpl implements BBSService { @Override public String bbsService(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); BBSDto article = new BBSDto(); String saveDir = req.getServletContext().getInitParameter("saveDirectory"); article.setId(req.getSession().getAttribute("id").toString()); article.setTitle(req.getParameter("title")); article.setContent(req.getParameter("content")); if(req.getPart("file").getSize() != 0) { Part filePart = req.getPart("file"); String originFileName = getFileName(filePart); article.setFileName(originFileName); File file = new File(saveDir + originFileName); InputStream is = filePart.getInputStream(); FileOutputStream fos = null; fos = new FileOutputStream(file); int temp = -1; while((temp = is.read()) != -1) { fos.write(temp); } is.close(); fos.close(); } try { if(BBSOracleDao.getInstance().insertArticle(article) == 1) { System.out.println("게시글이 삽입되었습니다."); } else { System.out.println("게시글 삽입이 실패하였습니다."); } } catch (Exception e) { e.printStackTrace(); } resp.sendRedirect("/bbs/list.bbs?pageNum=1"); return null; } public String getFileName(Part filePart) { for(String filePartData : filePart.getHeader("Content-Disposition").split(";")) { System.out.println(filePartData); if(filePartData.trim().startsWith("filename")) { return filePartData.substring(filePartData.indexOf("=") + 1).trim().replace("\"", ""); } } return null; } } | cs |
다중 파일 업로드의 경우 HTML5가 지원하는 input 태그의 multiple 속성을 이용하면 되는데, 이는 스프링 프로젝트에서 진행하도록 한다.
[서블릿 3.0에서 파일 업로드 참고]
[MultipartConfig annotation examples 참고1]
[multipart는 HTTP POST로만 전송해야 한다, Outsider's Dev Story 참고2]
'Java > web' 카테고리의 다른 글
[Spring] AspectJ 적용 시 NoClassDefFoundError, ClassNotFoundException 발생 (2) | 2017.05.22 |
---|---|
[모델2] 단일 파일 다운로드 구현하기 (게시판 구현) (0) | 2017.05.01 |
[Spring] MyBatis Mapper 파일 설정 방법 (0) | 2017.04.28 |
[Spring] JUnit 사용하기 (0) | 2017.04.26 |
[Spring] Jackson 라이브러리를 사용해 댓글 쓰기 구현하기 (게시판 구현) (0) | 2017.04.25 |