[Servlet / JSP] 파일 업로드 및 다운로드

suyeon·2022년 6월 24일
0

Servlet / JSP

목록 보기
8/9
post-thumbnail

파일 업로드 & 다운로드

  • 파일 업로드 : 클라이언트측 자원 -> 서버 전송(= 파일 복사)
  • 파일 다운로드 : 서버측 자원 -> 클라이언트 전송(= 파일 복사)

1. 라이브러리 추가하기

  1. www.servlets.com 사이트 접속
  1. COS File Upload Libray 클릭

  1. cos-22.05.zip 다운로드

  1. 압축 풀고 cos.jar 파일을 [프로젝트] > webapp > WEB-INF > lib > cos.jar 붙여넣기

  1. 업로드 파일을 올리기 위해 files 폴더 생성 ( webapp > example > files )

2. 파일 업로드

1) 화면 Form 작성

⭐ 3가지 필수 규칙

  1. <form method="POST">
  2. <input type="file">
  3. <form enctype="">
    a. application/x-www-form-urlencoded : 문자열 전송 (default)
    b. multipart/form-data : 문자열 + 비문자열 전송 (첨부 파일 전송)

File_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파일 업로드</title>
</head>
<body>
	<h1>파일 업로드</h1>

	<form method="POST" action="File_ok.jsp" enctype="multipary/from-data" 
			name="fileForm" onsubmit="return validateForm(this);">
		작성자 : <input type="text" name="name" value="suyeon" /><br />
		제목 : <input type="text" name="title" /><br />
		카테고리(선택사항) :
			<input type="checkbox" name="cate" value="사진" checked />사진
			<input type="checkbox" name="cate" value="공부" />공부
			<input type="checkbox" name="cate" value="취미" />취미
			<input type="checkbox" name="cate" value="음악" />음악<br />
		첨부파일 : <input type="file" name="attach" /><br />
		<input type="submit" value="전송하기" />
	</form>

	
	<script>
		function validateForm(form) {
			if (form.name.value == "") {
				alert("작성자를 입력하세요.");
				form.name.focus();
				return false;
			}
			if (form.title.value == "") {
				alert("제목을 입력하세요.");
				form.title.focus();
				return false;
			}
			if (form.attach.value == "") {
				alert("첨부파일을 넣어주세요.");
				return false;
			}
		}
	</script>
	
</body>
</html>

  • File_form.jsp를 실행하고, 모든 필수 입력값을 입력한 후 [전송하기] 버튼을 누르면 File_ok.jsp로 폼값이 전송된다.

  • 이렇게 전송된 파일을 서버에 업로드하고, 입력값은 DB에 저장한다.

2) DB 테이블 생성

테이블생성.sql

create table myfile (
    idx number primary key,                 -- 일련번호
    name varchar2(50) not null,             -- 작성자
    title varchar2(200) not null,           -- 제목
    cate varchar2(100),                     -- 카테고리
    ofile varchar2(100) not null,           -- 원본 파일명
    sfile varchar2(30) not null,            -- 저장된 파일명
    postdate date default sysdate not null  -- 등록한 날짜
);

3) DTO 및 DAO 클래스 생성

DTO.java

package fileupload;

public class MyfileDTO {
    // 멤버 변수
    private String idx; 
    private String name;   // 작성자 이름
    private String title;  // 제목
    private String cate;   // 카테고리
    private String ofile;  // 원본 파일명
    private String sfile;  // 저장된 파일명
    private String postdate; // 등록 날짜

    // 게터/세터
    public String getIdx() { 
        return idx;
    }
    public void setIdx(String idx) { 
        this.idx = idx;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getCate() {
        return cate;
    }
    public void setCate(String cate) {
        this.cate = cate;
    }
    public String getOfile() {
        return ofile;
    }
    public void setOfile(String ofile) {
        this.ofile = ofile;
    }
    public String getSfile() {
        return sfile;
    }
    public void setSfile(String sfile) {
        this.sfile = sfile;
    }
    public String getPostdate() {
        return postdate;
    }
    public void setPostdate(String postdate) {
        this.postdate = postdate;
    }
}

💬 DTO? DAO

  • DTO(Data Transfer Object) 는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(getter & setter 만 가진 클래스)이다.
  • 유저가 입력한 데이터를 DB에 넣는 과정.
    • 유저가 자신의 브라우저에서 데이터를 입력하여 form에 있는 데이터를 DTO에 넣어서 전송한다.
    • 해당 DTO를 받은 서버가 DAO를 이용하여 데이터베이스로 데이터를 집어넣는다.
  • DAO(Data Access Object) 는 데이터베이스의 data에 접근하기 위한 객체이다. DataBase에 접근 하기 위한 로직 & 비지니스 로직을 분리하기 위해 사용한다.

4) 파일 업로드 및 폼값 처리

1) encoding 설정 (String)

request.setCharacterEncoding("UTF-8");

2) 업로드된 파일이 저장될 디렉토리 위치 (String)

// 가상경로
String path = "C:\\class\\server\\JSPTest\\src\\main\\webapp\\example\\files";

// 물리경로
String path = application.getRealPath("/example/files");

💬 application

application은 해당 자바 어플리케이션 전역에서 사용될 수 있는 데이터를 저장하거나 가지고 있다.

파일을 업로드할 때는 이클립스의 workspace에 있는 프로젝트 디렉토리가 아니라, 아파치 톰캣이 실제 서버를 운영하기 위해서 원본 소스를 복사해놓은 실제 운영(배포) 디렉토리로 가야한다.

즉, 이클립스 workspace 안에 .metadata안에서 찾아야 한다.

C:\class\server\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPTest\example\files

이 경로를 application이 가지고 있고, 이 경로를 가져오기 위해서 application.getRealPath()를 사용하면 된다.

application.getRealPath("/") 하면 절대경로로서 c:/플젝명/까지를 말한다.

3) 업로드 파일의 최대 크기 지정 (int)

  • byte 단위
  • 한번에 업로드될 최대 용량
int size = 1024 * 1024 * 100; // 100MB

4) MultipartRequest 객체 생성

  • 파일 업로드 처리 구현
  • 객체 생성과 동시에 파일이 업로드되고, 객체 생성에 실패하면 파일은 업로드되지 않는다.
MultipartRequest multi = new MultipartRequest( request, // 원래의 request 객체
											   path,	// 업로드 위치
								 			   size,	// 최대 크기
											   "UTF-8",	// 인코딩 지정
									           new DefaultFileRenamePolicy()); // 동일한 파일명 관리 객체(중복 X)

5) 전송 데이터 가져오기

  • multipart/form-data 형식으로 전송 되었기 때문에 request.getParameter(), request.getParameterValues() 사용이 불가능하고, MultipartRequest 객체의 getParamter() 메소드를 사용해야 한다.
String userName = multi.getParameter("userName"); 

6) 모든 매개변수를 반환

  • <input type="file">인 모든 매개변수를 반환한다.
Enumeration files = multi.getFileNames();

7) 파일 정보 가져오기

ArrayList<String> filename = new ArrayList<String>(); 	 // 첨부파일명
ArrayList<String> orgfilename = new ArrayList<String>(); // 첨부파일명


while (files.hasMoreElements()) {		
			String file = (String)e.nextElement(); // file을 반환
			
			// 하드에 저장된 이름
			filename.add(multi.getFilesystemName(file));
			
			// 사용자가 올린 이름
			orgfilename.add(multi.getOriginalFileName(file));
		}

💬 MultipartRequest 주요 메소드

메소드내용
String getContentType(String name)어떤 형식의 파일인지 리턴
File getFile(String name)File 형식으로 리턴
Enumeration getFileNames()Enumeration 형식으로 업로드된 파일 이름들을 리턴
String getFilesystemName(String name)서버에 업로드된 파일이름 리턴
(동일한 파일이 존재하는 경우 파일이름이 변경됨)
String getOriginalFileName(String name)사용자가 업로드한 파일이름 리턴
(실제로 업로드한 파일의 원본 이름)
String getParameter(String name)인자값 받아오기
request.getParameter() 와 동일한 기능 수행
Enumeration getParameterNames()Enumeration 형식으로 인자값들 가져오기
String[] getParameterValues(String name)복수의 값들을 선택할 수 있는 경우, 값들 가져오기
(예를들어, checkbox에 사용할 수 있음)

8) 전체

<%@page import="java.util.Enumeration"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%

	request.setCharacterEncoding("UTF-8");

	String path = application.getRealPath("/example/files");
	
	int size = 1024 * 1024 * 100;
	
	String txt = ""; 		// 문자열
	String num = ""; 		// 숫자
	
	ArrayList<String> filename = new ArrayList<String>(); 	// 첨부파일명
	ArrayList<String> orgfilename = new ArrayList<String>(); // 첨부파일명
	
	try {
    
		MultipartRequest multi = new MultipartRequest(request, 	
													  path,		
													  size,		
												 	  "UTF-8",	
												      new DefaultFileRenamePolicy());
			
		txt = multi.getParameter("txt");
		num = multi.getParameter("num");
		
		Enumeration<?> e = multi.getFileNames();
		
		while (e.hasMoreElements()) {
			
			String file = (String)e.nextElement();
			filename.add(multi.getFilesystemName(file));			
			orgfilename.add(multi.getOriginalFileName(file));
		}
		
		} catch(Exception e) {
			System.out.println(e);
		}

%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<%@ include file="/example/inc/asset.jsp" %>
</head>
<body>

	<div class="container">
		<h1>결과</h1>
		
		<div>문자열: <%= txt %></div>
		<div>숫자: <%= num %></div>
		<div>첨부파일: <%= filename.size() %></div>
		<ul>
			<% for (int i=0; i<filename.size(); i++) { %>
			<li><a href="download.jsp?filename=<%= filename.get(i) %>&orgfilename=<%= orgfilename.get(i) %>"><%= orgfilename.get(i) %></a></li>
			<% } %>
		</ul>
	</div>

</body>
</html>

0개의 댓글