2021. 06. 02(수) TIL

Dylan·2021년 6월 3일
0
post-thumbnail

Servlet

MIME(Multipurpose Internet Mail Extensions) type

  • 클라이언트와 서버간에 주고받는 컨텐츠의 타입을 나타내는 것
  • 구조
    type/subType으로 구성되어 있다.
    • 예시
      text/plain
      text/html
      text/xml
      image/png
      image/jpg
      audio/mp3
      video/mp4
  • 대표적인 타입
    text
    - 인간이 읽을 수 있는 데이터 혹은 문서
    application
    - 모든 종류의 이진(바이너리) 데이터
    - 사람이 직접 읽을 수 없는 데이터 혹은 문서
    - 전용의 애플리케이션이 필요해
  • 대표적인 MIME타입
    text/plain
    - 일반 텍스트 데이터
    text/html
    - HTML 컨텐츠
    text/xml
    - XML 컨텐츠
    application/json
    - json 형식의 데이터
    application/octet-stream
    - 이진(바이너리) 데이터의 기본값
    - 타입이 알려지지 않은 이진(바이너리) 데이터를 의미함
    multipart/form-data
    - 브라우저에서 서버로 폼 입력값을 전송할 때 사용되는 변환방법 중 하나다.
    - 첨부파일이 있을 때 사용
    - [서버로 전송되는 형식]
    ----WebKitFormBoundaryQtk5bV9PVWAMOkEI
    Content-Disposition: form-data; name="title"
    휴가신청서
    application/x-www-form-urlencoded
    - 브라우저에서 서버로 폼 입력값을 전송할 때 사용되는 변환방법 중 하나다.
    - 첨부파일이 없을 때 사용
    - [서버로 전송되는 형식]
    - name=value&name=value&name=value
    		 

File Upload


<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ko">
	<head>
		<title>Bootstrap 4 Example</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
		<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
	</head>
	<body>
		<div class="container">
			<div class="row mt-3">
				<div class="col-12">
					<h3>파일 업로드 폼</h3>
					<!--
						enctype
							- 폼 입력값을 서버로 전송할 때 사용되는 인코딩(변환)방식을 지정하는 속성이다.
							- 기본값은 "application/x-www-form-urlencoded"이다.
							
							- enctype="application/x-www-form-urlencoded"
								- 폼입력값을 name=value&name=value&name=value로 변환해서 전송한다.
								- name은 폼 입력요소의 name 속성에 지정된 이름이다.
								- [변환예시]
									title=휴가신청서&description=휴가신청시 다운받아서 작성하세요&upfile=신청서.hwp
								- 첨부파일이 없는 폼 입력값 제출에 사용된다.
							- enctype="multipart/form-data"
								- 첨부파일이 포함된 폼 입력값을 제출할 때 사용되는 인코딩 방식이다.
								- 요청메세지의 요청파라미터값을 request.getParameter(String name)로 조회할 수 없다.
								- 요청메세지의 요청파라미터값, 업로드되는 첨부파일 처리를 위한 추가 라이브러리가 필요함
									cos.jar, commons-fileupload.jar 등이 필요함
								- [변환예시]
									 ----WebKitFormBoundaryQtk5bV9PVWAMOkEI
				                     Content-Disposition: form-data; name="title"
				                     휴가신청서
				                     
				                     ----WebKitFormBoundaryQtk5bV9PVWAMOkEI
				                     Content-Disposition: form-data; name="description"
				                     휴가 신청시 작성해서 제출하세요
				                     
				                     ----WebKitFormBoundaryQtk5bV9PVWAMOkEI
				                     Content-Disposition: form-data; name="upfile"; filename="휴가신청서.hwp"
				                     Content-Type: application/x-hwp
				
				                     ----WebKitFormBoundaryQtk5bV9PVWAMOkEI
					-->
					<form method="post" action="/upload" enctype="multipart/form-data">
						<div class="form-group">
							<label>제목</label>
							<input type="text" class="form-control" name="title"/>
						</div>
						<div class="form-group">
							<label>설명</label>
							<textarea rows="3" class="form-control" name="description"></textarea>
						</div>
						<div class="form-group">
							<label>첨부파일</label>
							<input type="file" class="form-control" name="upfile" />
						</div>
						<div class="text-right">
							<a href="../index.jsp" class="btn btn-secondary">취소</a>
							<button type="submit" class="btn btn-primary">등록</button>
						</div>
					</form>
				</div>
			</div>	
		</div>
	</body>
</html>

/*
 * @WebServlet
 * 		- 이 클래스가 클라이언트의 HTTP 요청을 처리하는 서블릿 클래스임을 나타낸다
 *  	- ("/upload")는 이 서블릿 클래스와 매핑된 URI를 설정한다
 *  	  위의 설정은 http://localhost/upload라는 요청이 접수되면 이 서블릿의
 *  	  void service(request, response) 메소드가 실행되게 한다
 */
@WebServlet("/upload")
/*
 * @MultipartConfig
 * 		- 이 클래스가 멀티파트요청을 처리하는 서블릿 클래스임을 나타낸다.
 * 		- 멀티파트요청은 폼 입력요소에 첨부파일 업로드가 포함되어 있는 요청이다.
 * 		- 멀티파트요청은 <form />태그에 enctype="multipart/form-data"로 설정되어 있는 것이다.
 * 		- @MultipartConfig 어노테이션이 부착되어 있지 않는 서블릿 클래스는 멀티파트요청을 처리할 수 없다.
 */
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

	private static final String saveDirectory = "C:\\workspace\\Central_HTA\\java-web\\upload";
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 요청 파라미터 조회하기
		String title = request.getParameter("title");
		String description = request.getParameter("description");
		System.out.println("제목 : " + title);
		System.out.println("설명 : " + description);
		
		// 업로드된 첨부파일 처리하기
		// Part는 업로드된 첨부파일의 정보를 가지고 있는 객체다.
		// Part로부터 파일명, 파일종류(ContentType), 파일크기, 파일을 읽어오는 스트림을 획득할 수 있다.
		Part part = request.getPart("upfile");
		
		// 1. 업로드된 첨부파일 정보 획득하기
		String filename = System.currentTimeMillis() + part.getSubmittedFileName();
		
		// 2. 업로드된 첨부파일을 지정된 폴더에 복사하기
		// 	  * 서버로 업로드된 첨부파일은 서버의 임시디렉토리에 임시파일(xxxxxxxx.tmp)의 형태로 저장되어 있음
		// File객체 생성 : 지정된 디렉토리와 파일명에 대한 정보를 가지는 객체다
		//					실제로 존재하지 않는 파일에 대해서도 객체 생성이 가능하다.
		
        	// 첨부파일을 디스크에 저장하는 출력스트림 생성
		OutputStream out = new FileOutputStream(new File(saveDirectory, filename));
		// 임시폴더에 저장된 첨부파일을 읽어오는 스트림 획득
		InputStream in = part.getInputStream();
		// 입력스트림으로 읽어온 데이터를 출력스트림으로 출력시켜서 파일을 복사한다.
		IOUtils.copy(in, out);
		out.close();
		
		// 3. 업로드된 파일정보(제목, 설명, 파일명)을 데이터베이스에 저장하기
		FileItem fileItem = new FileItem();
		fileItem.setTitle(title);
		fileItem.setDescription(description);
		fileItem.setFilename(filename);
		
		FileItemDao fileItemDao = FileItemDao.getInstance();
		fileItemDao.insertFileItem(fileItem);
		
		
		// 클라이언트에게 index.jps를 재요청하게 하는 응답을 보내기
		response.sendRedirect("/index.jsp");
	}
}

File Download


@WebServlet("/download")
public class FileDownloadServlet extends HttpServlet {
	
	private static final String saveDirectory = "C:\\workspace\\Central_HTA\\java-web\\upload";
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 요청파라미터값 조회
		// http://localhost/download?no=파일번호
		int fileNo = Integer.parseInt(request.getParameter("no"));
		
		// 데이터베이스에서 파일정보 조회
		FileItemDao fileItemDao = FileItemDao.getInstance();
		FileItem fileItem = fileItemDao.getFileItem(fileNo);
		String filename = fileItem.getFilename();
		
		// 획득된 파일이름에 해당하는 파일을 읽어서 클라이언트에게 응답으로 출력하기
		// 파일 --> InputStream --> OutputStream --> 브라우저
		
		// 파일 다운로드 하기
		
		// 1. 응답컨텐츠 타입과 파일이름 설정하기
		// "application/octet-stream" 은 임의의 바이너리 데이터에 대한 컨텐츠 타입이다. 
		response.setContentType("application/octet-stream");
		// 다운로드되는 파일의 이름을 응답메세지의 헤더에 설정한다.
		String shortFilename = fileItem.getShortFilename();
		shortFilename = URLEncoder.encode(shortFilename, "utf-8");
		response.setHeader("Content-Disposition", "attachment; filename=" + shortFilename);
		
		// 2. 파일을 읽어서 브라우저와 연결된 출력스트림으로 내려보내기
		// 저장된 파일을 읽어오는 스트림 생성
		InputStream in = new FileInputStream(new File(saveDirectory, filename));
		// 브라우저와 연결된 출력 스트림 획득
		OutputStream out = response.getOutputStream();
		IOUtils.copy(in, out);
		IOUtils.close();
	}
}

0개의 댓글

관련 채용 정보