공부의 기록/자바 풀 스택 : 수업내용정리

자바 풀 스택 1/13 오후 기록 036-2

파티피플지선 2025. 1. 13. 18:21

<14:30 5교시>


 
 
다운로드 기능 넣어보기

package test.servlet;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/file/download")
public class FileDownServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//다운로드 작업에 필요한 3가지 정보(원본파일명, 저장된파일명, 파일의크기) 얻어오기
		// 지금은 파라미터로 전달되지만 실제로는 DB에 저장된 정보를 읽어와서 다운로드 해야 함
		String origFileName=request.getParameter("origFileName");
		String saveFileName=request.getParameter("saveFileName");
		long fileSize=Long.parseLong(request.getParameter("fileSize"));
		
		//응답 헤더 정보 설정
		response.setHeader("Content-Type", "application/octet-stream; charset=UTF-8");
		//다운로드 시켜줄 파일명 인코딩  
	   	String encodedName=URLEncoder.encode(origFileName, "utf-8");
		//파일명에 공백이있는 경우 처리 
		encodedName=encodedName.replaceAll("\\+"," ");
		
		response.setHeader("Content-Disposition", "attachment;filename="+encodedName);
		response.setHeader("Content-Transfer-Encoding", "binary");
		
		//다운로드할 파일의 크기
		response.setContentLengthLong(fileSize);
		
		//다운로드 시켜줄 파일의 실제 경로
		String path=getServletContext().getRealPath("/upload")+File.separator+saveFileName;
		
		FileInputStream fis=null;
		BufferedOutputStream bos=null;
		try {
			//파일에서 byte 을 읽어들일 객체
			fis=new FileInputStream(path);
			//클라이언트에게 출력할수 있는 스트림 객체 얻어오기
			bos=new BufferedOutputStream(response.getOutputStream());
			//한번에 최대 1M byte 씩 읽어올수 있는 버퍼
		   	byte[] buffer=new byte[1024*1024];
		   	int readedByte=0;
		   	//반복문 돌면서 출력해주기
		   	while(true) {
		   		//byte[] 객체를 이용해서 파일에서 byte 알갱이 읽어오기
		   		readedByte = fis.read(buffer);
		   		if(readedByte == -1)break; //더이상 읽을 데이터가 없다면 반복문 빠져 나오기
		   		//읽은 만큼 출력하기
		   		bos.write(buffer, 0, readedByte);
		   		bos.flush(); //출력
		   	}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(fis!=null)fis.close();
			if(bos!=null)bos.close();
		}	
	}
}

 
 
 
Ctrl + Shift + O 를 누르면 일괄 import 가능하다

 
 
 
 
<15:30 6교시>
Step06ETC/upload/saveFileName 형태의 경로를 알아두자.
 
upload_form2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h3>이미지업로드 폼</h3>
		<form action="${pageContext.request.contextPath}/file/upload2" method="post" enctype="multipart/form-data">
			<input type="text" name="title" placeholder="설명입력"/><br />
			이미지 <input type="file" name="myImg" accept="image/*" /><br />
			<button type="submit"> 업로드 </button>
		</form>
	
	</div>
</body>
</html>

 
 
UploadServlet2.java

package test.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
@WebServlet("/file/upload2")
@MultipartConfig(
		fileSizeThreshold = 1024*1024*5,//메모리 임계값 (메모리를 효율적으로 쓰기 위한 값, 이 값을 넘어가면 파일로 전환함)
		maxFileSize=1024*1024*50, //최대 파일 사이즈 1킬로바이트(=1024바이트)*1킬로바이트*50 =50메가 바이트
		maxRequestSize=1024*1024*60//최대 요청 사이즈 
		)
public class UploadServlet2 extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//업로드될 실제 경로 얻어내기
		String uploadPath=getServletContext().getRealPath("/upload");
		File uploadDir=new File(uploadPath);
		//만일 upload 폴더가 존재하지 않으면
		if(!uploadDir.exists()) {
			uploadDir.mkdir();//실제로 폴더 만들기
		}
		
		String title=req.getParameter("title");
		
		//파일명이 겹치지 않게 저장하기 위한 랜덤한 문자열을 얻어내기
		String uid=UUID.randomUUID().toString();
		System.out.println(uid);
		String origFileName=null;
		String saveFileName=null;
		
		//파일 데이터 처리는 좀 다르다
		Part filePart = req.getPart("myImg");
		if(filePart !=null) {
			//파일 이름 얻어내기
			origFileName=filePart.getSubmittedFileName();
			//저장될 파일의 이름 구성하기
			saveFileName=uid+origFileName;
			//저장할 파일의 경로 구성
			String filePath=uploadPath+File.separator+ saveFileName;
			//파일 저장
			InputStream is=filePart.getInputStream();
			Files.copy(is, Paths.get(filePath));
		}
		
		//파일의 크기 얻어내기(큰 정수이기 때문에 long type 사용)
		long fileSize=filePart.getSize();
		
		//응답에 필요한 데이터를 request 영역에 담기
		req.setAttribute("title", title);
		req.setAttribute("origFileName", origFileName);
		req.setAttribute("saveFileName",saveFileName );
		req.setAttribute("fileSize", fileSize);
		req.setAttribute("uploadPath", uploadPath);
		//나중에 이걸 리눅스에 올릴 때 uploadPath 확인할 필요가 있어서
		
		//jsp 페이지로 응답을 위임하기(리다이렉트는 컨텍스트 경로가 필요하지만 포워드 이동은 필요 없다)
		RequestDispatcher rd=req.getRequestDispatcher("/file/upload2.jsp");
		rd.forward(req, resp);
	}
	
}

 
 
upload2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>업로드 결과 페이지</h1>
		<p>파일을 업로드했습니다.</p>
		<p>title : <strong> ${requestScope.title }</strong></p>
		<p>origFileName: <strong>${origFileName}</strong></p>
		<p>saveFileName: <strong>${saveFileName}</strong></p>
		<p>fileSize : <strong>${fileSize}</strong></p>
		<p>uploadPah: <strong>${uploadPath}</strong></p>
		<p><a href="${pageContext.request.contextPath}/file/download?origFileName=${origFileName}&saveFileName=${saveFileName}&fileSize=${fileSize}">다운로드</a></p>
		<img src="${pageContext.request.contextPath}/upload/${saveFileName}" alt="업로드된 이미지" />
	</div>
</body>
</html>

 
 
 
오브젝트 작성법을 잘 해야 자바스크립트를 잘 한다.
 

UploadServlet3.java

package test.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
@WebServlet("/file/upload3")
@MultipartConfig(
		fileSizeThreshold = 1024*1024*5,//메모리 임계값 (메모리를 효율적으로 쓰기 위한 값, 이 값을 넘어가면 파일로 전환함)
		maxFileSize=1024*1024*50, //최대 파일 사이즈 1킬로바이트(=1024바이트)*1킬로바이트*50 =50메가 바이트
		maxRequestSize=1024*1024*60//최대 요청 사이즈 
		)
public class UploadServlet3 extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//업로드될 실제 경로 얻어내기
		String uploadPath=getServletContext().getRealPath("/upload");
		File uploadDir=new File(uploadPath);
		//만일 upload 폴더가 존재하지 않으면
		if(!uploadDir.exists()) {
			uploadDir.mkdir();//실제로 폴더 만들기
		}
		
		String title=req.getParameter("title");
		
		//파일명이 겹치지 않게 저장하기 위한 랜덤한 문자열을 얻어내기
		String uid=UUID.randomUUID().toString();
		System.out.println(uid);
		String origFileName=null;
		String saveFileName=null;
		
		//파일 데이터 처리는 좀 다르다
		Part filePart = req.getPart("myImg");
		if(filePart !=null) {
			//파일 이름 얻어내기
			origFileName=filePart.getSubmittedFileName();
			//저장될 파일의 이름 구성하기
			saveFileName=uid+origFileName;
			//저장할 파일의 경로 구성
			String filePath=uploadPath+File.separator+ saveFileName;
			//파일 저장
			InputStream is=filePart.getInputStream();
			Files.copy(is, Paths.get(filePath));
		}
		
		//파일의 크기 얻어내기(큰 정수이기 때문에 long type 사용)
		long fileSize=filePart.getSize();
		
		//응답에 필요한 데이터를 request 영역에 담기
		req.setAttribute("title", title);
		req.setAttribute("origFileName", origFileName);
		req.setAttribute("saveFileName",saveFileName );
		req.setAttribute("fileSize", fileSize);
		req.setAttribute("uploadPath", uploadPath);
		//나중에 이걸 리눅스에 올릴 때 uploadPath 확인할 필요가 있어서
		
		//jsp 페이지로 응답을 위임하기(리다이렉트는 컨텍스트 경로가 필요하지만 포워드 이동은 필요 없다)
		RequestDispatcher rd=req.getRequestDispatcher("/file/upload3.jsp");
		rd.forward(req, resp);
	}
	
}




upload3.jsp

<%@ page language="java" contentType="application/json; charset=UTF-8"
    pageEncoding="UTF-8"%>
{
	"title":"${title}",
	"origFileName":"${origFileName}",
	"saveFileName":"${saveFileName}",
	"fileSize":${fileSize}
}

 
 
 
<16:30 7교시>
index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>인덱스 페이지</h1>
		<ul>
			<li><a href="test_cookie/cookie_form.jsp">쿠키 테스트</a></li>
			<li><a href="file/upload_form.jsp">파일 업로드 테스트</a></li>
			<li><a href="file/upload_form2.jsp">이미지 업로드 테스트</a></li>
			<li><a href="file/upload_form3.jsp">페이지 전환 없이 이미지 업로드 테스트</a></li>
			<li><a href="file/upload_form4.jsp">이미지 단독 업로드</a></li>
		</ul>
	</div>
</body>
</html>

 
upload_form3.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
		<div class="container">
		<h3>이미지 업로드 폼</h3>
		<form action="${pageContext.request.contextPath}/file/upload3" method="post" enctype="multipart/form-data" id="myForm">
			<input type="text" name="title" placeholder="설명 입력"/><br />
			이미지 <input type="file" name="myImg" accept="image/*"/><br />
			<button type="submit">업로드</button>
		</form>
		<img id="image" width="300"/>
	</div>
	<script>
		document.querySelector("#myForm").addEventListener("submit", (event)=>{
			//기본동작(폼제출)을 막기
			event.preventDefault();
			//event.target=>해당 이벤트가 발생한 바로 그 요소의 참조값(즉 여기서는 form의 참조값이 된다)
			//document.querySelector("#myForm")==event.target 동일 값
			const data=new FormData(event.target);
			//fetch 함수를 이용해서 FormData 전송하기
			fetch("${pageContext.request.contextPath}/file/upload3", {
				method:"post",
				body:data
			})//옵션으로 전달하는 키값은 보통 정해져 있다.
			.then(res=>res.json())
			.then(data=>{
				console.log(data);
				//data.saveFileName은 upload 폴더에 저장된 파일명이다.
				const requestPath="${pageContext.request.contextPath}/upload/"+data.saveFileName;
				document.querySelector("#image").setAttribute("src", requestPath);		
			});
		}); 
	</script>
</body>
</html>

 
 
 
글자, svg는  벡터 이미지이다. 
 
 
<17:30 8교시> 
오늘 한 거 복습하기
내일 upload_form4.jsp 기능 만들어보기할 거 미리 해보기