[JSP/Servlet] 파일처리(파일 업로드) / 서블릿 파일 업로드
by mini_min[JSP/Servlet] 파일처리(파일 업로드) / 서블릿 파일 업로드
✔️ 파일 업로드를 위한 <form> 태그
: <form> 태그 안에 정의된 요청 파라미터를 클라이언트에서 서버로 전송할 때 인코딩 방법을 지정한다.
: method 속성이 post 인 경우에만 속성은 유효하다.
👩💻 속성값
1. application/x-www-form-urlencoded
: 기본 enctype 속성으로 해당 콘텐츠 타입은 바이너리 데이터(파일 등) 을 전송할 수 없다.
2. multipart/form-data
: 문자 인코딩을 하지 않고 전송되며, 파일을 전송할 때 사용한다.
: 여러 형태의 데이터(파일 내용, 텍스트 입력 값) 이 동시에 전달되며, 각 데이터는 [boundary = ....] (경계 정보) 뒤에 붙은 문자열을 이용하여 구분된다.
3. text/plan
: 공백이 + 문자로 변환되며 특수 문자를 인코딩 하지 않는다.
✔️ enctype 이 기본인 경우
: 파일을 전송해도 파일은 파일 이름만 전송된다. (내용전달x)
<h3>파일 업로드</h3>
<%--
form 태그에서 enctype 을 생략하면 application/x-www-form-urlencoded (기본)
- application/x-www-form-urlencoded 은 파라미터를 주소형식으로 인코딩하여 전송한다.
파라미터는 "이름1=값1&이름2=값2" 형태로 body 영역에 실어서 보냄
- application/x-www-form-urlencoded 속성 값에서 파일을 전송하면 파일은 파일 이름만 전송된다.
- enctype는 method가 post 에서만 유효하다.
--%>
<form action="ex01_ok.jsp" method="post" enctype="application/x-www-form-urlencoded">
<p> 제목 : <input type="text" name="subject"></p>
<p> 파일 : <input type="file" name="selectFile"></p>
<p>
<button type="submit">확인</button>
</p>
</form>
✔️ enctype이 multipart/form-data 인 경우
: 문자 인코딩 없이 그대로 전달되며, 파일을 전송하는 경우에 사용한다.
: 파일 내용도 함께 전송된다.
: 파라미터는 request.getParameter 로 받을 수 없음
<h3>파일 업로드</h3>
<%--
form 태그에서 enctype을 multipart/form-data 로 준 경우
: 문자를 인코딩하지 않고 그대로 전송하며, 파일을 전송해야 하는 경우에 사용한다.
: 파일 내용도 같이 전송
- enctype는 method가 post 에서만 유효하다.
--%>
<form action="ex02_ok.jsp" method="post" enctype="multipart/form-data">
<p> 제목 : <input type="text" name="subject"></p>
<p> 파일 : <input type="file" name="selectFile"></p>
<p>
<button type="submit">확인</button>
</p>
</form>
- 요청 받은 정보 출력하기 ✨
: 웹과 JSP 에서 enctype은 contenttype 이다.
결과 : multipart/form-data; boundary=----WebKitFormBoundarylrnP16LoJSIqSN1I
- 헤더정보
: 헤더정보는 Enumeration 클래스를 통해 출력할 수 있다.
- request body 영역으로 넘어온 데이터도 출력 가능하다.
: inputStream 이용하여 데이터 정보를 출력한다.
<h3> 요청 받은 정보 </h3>
<%
//웹, jsp 에서 enctype 은 contenttype이다.
String contentType = request.getContentType();
out.print("<p>contentType(enctype) : " + contentType + "</p>");
out.print("<hr>");
out.print("<h3>[헤더 정보]...</h3>");
Enumeration<String> e = request.getHeaderNames();
while(e.hasMoreElements()){
String name = e.nextElement();
String value = request.getHeader(name);
out.print("<p>" + name + " : " + value + "</p>");
}
out.print("<hr>");
out.print("<h3>[request body 영역으로 넘어온 데이터]...</h3>");
InputStream is = request.getInputStream();
byte[] buf = new byte[2048];
int size;
String str;
while((size = is.read(buf))!= -1){
str = new String(buf, 0, size, "utf-8");
out.print("<p>" + str + "</p>");
}
out.print("<hr>");
%>
✔️ cos.jar 을 이용한 파일 업로드.
: cos.jar 을 이용해서 파일을 업로드할 수 있다.
MultipartRequest mreq = new MultipartRequest(request, pathname, maxSize, encType,
new DefaultFileRenamePolicy());
<%
request.setCharacterEncoding("utf-8");
// /study3 경로의 실제 경로(로컬컴퓨터의 위치)
String root = session.getServletContext().getRealPath("/");
String pathname = root + "uploads" + File.separator + "pds";
File f= new File(pathname);
if( ! f.exists()){ //폴더가 없으면 폴더 만들어라는 뜻
f.mkdirs();
}
String encType = "utf-8";
int maxSize = 5 * 1024 * 1024; // 5MB
//cos.jar 을 이용한 파일 업로드
//request, 파일저장위치, 최대파일크기, 파라미터인코딩, 중복파일보호
MultipartRequest mreq = new MultipartRequest(request, pathname, maxSize, encType,
new DefaultFileRenamePolicy());
// 제목
String subject = mreq.getParameter("subject");
//서버에 저장된 파일 이름
String saveFilename = mreq.getFilesystemName("selectFile");
//클라이언트가 올린 파일 이름
String originalFilename = mreq.getOriginalFileName("selectFile");
//파일크기
long fileSize = 0;
File file = mreq.getFile("selectFile");
if(file != null){
fileSize = file.length();
}
%>
<form action="ex03_ok.jsp" method="post" enctype="multipart/form-data">
<p> 제목 : <input type="text" name="subject"></p>
<p> 파일 : <input type="file" name="selectFile"></p>
<p>
<button type="submit">확인</button>
</p>
</form>
✔️ 서블릿 3.0 에서의 파일 업로드
: 서블릿 3.0부터는 파일을 업로드 하기 위해 multipart/form-data Content Type 으로 요청된 정보는 다른 API 를 사용하지 않고 파일을 업로드하는 방법을 지원한다.
: HttpServletRequest 는 multipart/form-data Content Type 으로 요청된 모든 Part 를 가져오는 메소드를 제공한다.
📓 Part 관련 메소드
: getParts() : 업로드된 모든 Part 를 Collection 으로 반환한다.
: getPart(String name) : 저장된 이름의 Part를 반환하고, 없으면 null을 반환한다.
📓 Part 인터페이스의 주요 메소드
: getName() : 이 Part 에 해당하는 multipart 폼 양식의 필드 이름을 반환한다.
: getContentType() : 브라우저가 전달한 Content type을 반환한다. 정의되지 않았으면 null 을 반환한다.
: getInputStream() : 이 Part의 InputStream 객체를 반환한다.
: getHeaderName() : 이 Part 에 제공된 모든 헤더의 이름을 Collection 으로 반환한다.
: getSize() : 이 Part 의 크기를 반환한다.
: write(String fileName) : 업로드된 파일을 디스크에 저장한다.
: delete() : 이 Part에 관련된 임시 파일 및 Part의 기본 저장소를 지운다.
👩💻 @MultipartConfig 어노테이션
: 서블릿의 인스턴스가 multipart/form-data MIME 형식의 요청을 처리하기 위한 설정을 구성하는 어노테이션이다.
📓 속성
- fileSizeThreshold : 파일이 디스크에 기록될 때까지의 크기 임계 값이다. 값의 단위는 바이트
- location : 파일이 기본적으로 저장될 디렉토리이며 기본값은 ""
- maxFileSize : 파일을 업로드할 수 있는 최대 크기. 단위는 바이트. 기본값은 무한을 의미하는 -1L
- maxRequestSize : multipart/form-data 요청에 허용되는 최대 크기이며 기본값은 무한을 의미하는 -1L
- form 양식
<h3> 서블릿 3.0이상 을 이용한 파일 </h3>
<form action="${pageContext.request.contextPath}/upload/write_ok.do"
method="post" enctype="multipart/form-data">
<p> 제목 : <input type="text" name="subject"></p>
<p> 파일 : <input type="file" name="selectFile"></p>
<p>
<button type="submit">확인</button>
</p>
</form>
- 서블릿 (TestServlet)
: @MultipartConfig 어노테이션을 사용하면, 파일 이외의 파라미터는 request.getParameter 사용 가능
: 하나의 파라미터 당 Part 객체 하나가 생성된다.
: Part 객체 얻는 방법 : Part p = req.getPart("이름");
: 모든 Part 객체 반환은 Collection + getParts();
/*
* @MultipartConfig
- 서블릿 3.0 부터 파일 업로드를 지원하는 어노테이션
- @MultipartConfig 애노테이션을 사용하면 enctype= "multipart/form-data" 로 넘어온
파일 이외의 파라미터는 req.getParameter("이름")으로 넘겨 받을 수 있다!!(없으면안됨)
- 하나의 파라미터당 하나의 Part 객체가 만들어 진다.
예를 들어, "이름, 제목, selectFile 이름으로 파일 두개"를 전송하면
Part 객체는 4개 만들어진다.
- Part 객체의 메소드를 이용하여 간단히 파일 업로드가 가능하다.
- Part 객체는 다음과 같이 얻는다.
Part p = req.getPart("이름");
- 모든 Part 객체 반환
Collection<Part> pp = req.getParts();
*/
- dopost, doget, forward, execute 생략...
: if(! f.exists()) : 해당되는 이름의 파일이 없으면 생성하기
protected void form(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
forward(req, resp, "/WEB-INF/views/upload/write.jsp");
}
protected void submit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
String root = session.getServletContext().getRealPath("/");
String pathname = root + "uploads" + File.separator + "pds";
File f = new File(pathname);
if(! f.exists()) {
f.mkdirs();
}
//제목 받기
String subject = req.getParameter("subject");
//파일 받기
Part p = req.getPart("selectFile");
String originalFilename = getOriginalFilename(p);
long fileSize = 0;
String saveFilename = null;
//이름 같은 파일들이 있으면 덮어버림
if(originalFilename != null) { //서버에 올라온 파일이 있으면
//중복 만나지않고 서버에 저장하는 방법 생각
//확장자(.확장자)
String fileExt = originalFilename.substring(originalFilename.lastIndexOf("."));
//서버에 저장할 파일이름 만들기
saveFilename = String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", Calendar.getInstance());
saveFilename += System.nanoTime();
saveFilename += fileExt;
//서버에 파일 저장하기
String path = pathname + File.separator + saveFilename;
p.write(path);
fileSize = p.getSize();
}
req.setAttribute("subject", subject);
req.setAttribute("pathname", pathname);
req.setAttribute("originalFilename", originalFilename);
req.setAttribute("saveFilename", saveFilename);
req.setAttribute("fileSize", fileSize);
forward(req, resp, "/WEB-INF/views/upload/result.jsp");
}
//클라이언트가 올린 파일 이름
private String getOriginalFilename(Part p) {
String []ss = p.getHeader("content-disposition").split(";");
for(String s : ss) {
if(s.trim().startsWith("filename")) {
return s.substring(s.indexOf("=")+1).trim().replace("\"", "");
}
}
return null;
}
'JSP' 카테고리의 다른 글
[jQuery] jQuery append 요소 추가, 요소 삭제 (0) | 2022.10.19 |
---|---|
[jQuery] jQuery 정의 셀렉터 요소 접근 (0) | 2022.10.19 |
[Servlet] 방명록 기능 Servlet (0) | 2022.10.10 |
[JSP] 세션 Session 설정하기 지우기 (0) | 2022.10.10 |
[JSP] 쿠키 설정 / 가져오기 (Cookie) (0) | 2022.10.10 |
블로그의 정보
개발자 미니민의 개발로그
mini_min