MultipartRequest를 사용한 다중 파일 업로드!
MultipartRequest
What & Why**
전체 흐름:
사용자 → 다중 폼(JSP) → 서블릿 → 결과페이지(JSP)Why MultipartRequest vs DiskFileUpload?
- MultipartRequest: 간단하고 직관적, 코드가 짧음
- DiskFileUpload: 더 세밀한 제어 가능, 복잡함
- 다중 파일: 한 번에 여러 파일 + 텍스트 처리
Key 차이점:
- 자동 저장: MultipartRequest는 생성하는 순간 파일이 자동 저장됨
- 웹앱 내부:
resources/images폴더에 저장 (웹에서 바로 접근 가능)
1단계: 단일 파일 폼부터 ⭐
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파일 업로드</title>
</head>
<body>
<h2>단일 파일 업로드</h2>
<form method="post" enctype="multipart/form-data" action="exam7_2">
<p> 이름: <input type="text" name="name1">
<p> 제목: <input type="text" name="subject1">
<p> 파일: <input type="file" name="filename1">
<p> <input type="submit" value="업로드">
</form>
</body>
</html>
🔍 핵심 포인트:
action="exam7_2"← 서블릿 이름 (자유롭게 변경 가능)name="name1","subject1","filename1"← 변수명 (자유롭게 변경 가능)
🛠️ 2단계: 서블릿 뼈대 ⭐⭐
package chapter07;
import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest; // ✨ 핵심!
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy; // ✨ 중복 파일명 처리
@WebServlet("/exam7_2") // ← URL 패턴 (자유롭게 변경 가능)
public class exam7_2 extends HttpServlet {
// GET: 폼 페이지 보여주기
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("7_2 doget 예제 연결.");
RequestDispatcher ds = req.getRequestDispatcher("chapter07/fileupload02.jsp");
ds.forward(req, resp);
}
// POST: 파일 업로드 처리 (단일 파일)
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("7_2 dopost 예제 연결.");
// ✨ MultipartRequest 5개 매개변수 설정
String save = req.getServletContext().getRealPath("/resources/images"); // 저장 경로
int max = 1024*1024*5; // 최대 크기 5MB (변경 가능)
String encoding = "utf-8"; // 인코딩 (변경 가능)
DefaultFileRenamePolicy rename = new DefaultFileRenamePolicy(); // 중복 파일명 처리
// ✨ 핵심: MultipartRequest 생성 = 파일 자동 저장!
MultipartRequest multi = new MultipartRequest(req, save, max, encoding, rename);
// 데이터 가져오기
String name1 = multi.getParameter("name1");
String subject1 = multi.getParameter("subject1");
String filename1 = multi.getFilesystemName("filename1"); // 파일명
System.out.println("이름: " + name1 + ", 제목: " + subject1 + ", 파일: " + filename1);
// JSP로 데이터 전달
req.setAttribute("name1", name1);
req.setAttribute("subject1", subject1);
req.setAttribute("filename1", filename1);
RequestDispatcher ds = req.getRequestDispatcher("chapter07/fileupload02_process.jsp");
ds.forward(req, resp);
}
}
🔍 핵심 포인트:
- MultipartRequest 5개 매개변수:
(request, 저장폴더, 크기, 인코딩, 이름중복정책) - 자동 저장:
new MultipartRequest()하는 순간 파일이 저장됨! - getParameter(): 텍스트 데이터
- getFilesystemName(): 실제 저장된 파일명
📄 3단계: 결과 페이지 ⭐
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>업로드 결과</title>
</head>
<body>
<%
String name1 = (String) request.getAttribute("name1");
String subject1 = (String) request.getAttribute("subject1");
String filename1 = (String) request.getAttribute("filename1");
%>
<h2>업로드 결과</h2>
<h3>이름: <%= name1 %>, 제목: <%= subject1 %>, 파일: <%= filename1 %></h3>
<!-- ✨ 이미지 표시 (웹앱 내부라서 바로 접근 가능!) -->
<img src="/JSPBook/resources/images/<%= filename1 %>" width="300" height="300">
<br><br>
<a href="exam7_2">다시 업로드하기</a>
</body>
</html>
🔍 핵심 포인트:
- 이미지 경로:
/JSPBook/resources/images/파일명 - 웹에서 바로 접근: resources 폴더는 웹에서 직접 접근 가능
- C드라이브 vs 웹앱: DiskFileUpload는 C드라이브(웹 접근 불가), MultipartRequest는 웹앱 내부(웹 접근 가능)
⚡ 4단계: 다중 파일로 확장 ⭐⭐⭐
4-1: 폼을 다중 파일로 확장
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>다중 파일 업로드</title>
</head>
<body>
<h2>다중 파일 업로드</h2>
<form method="post" enctype="multipart/form-data" action="exam7_2">
<!-- ✨ 첫 번째 파일 세트 -->
<p> 이름1: <input type="text" name="name1">
<p> 제목1: <input type="text" name="subject1">
<p> 파일1: <input type="file" name="filename1">
<!-- ✨ 두 번째 파일 세트 -->
<p> 이름2: <input type="text" name="name2">
<p> 제목2: <input type="text" name="subject2">
<p> 파일2: <input type="file" name="filename2">
<!-- ✨ 세 번째 파일 세트 -->
<p> 이름3: <input type="text" name="name3">
<p> 제목3: <input type="text" name="subject3">
<p> 파일3: <input type="file" name="filename3">
<p> <input type="submit" value="파일올리기">
</form>
</body>
</html>
🔍 변경사항:
- name 속성:
name1, name2, name3/subject1, subject2, subject3/filename1, filename2, filename3 - 패턴: 숫자로 구분해서 여러 세트
4-2: 서블릿에서 다중 파일 처리
package chapter07;
import java.io.IOException;
import java.util.Enumeration; // ✨ 추가
import java.util.HashMap; // ✨ 추가
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
@WebServlet("/exam7_2")
public class exam7_2 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("7_2 doget 예제 연결.");
RequestDispatcher ds = req.getRequestDispatcher("chapter07/fileupload02.jsp");
ds.forward(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("7_2 dopost 예제 연결.");
// MultipartRequest 설정 (동일)
String save = req.getServletContext().getRealPath("/resources/images");
System.out.println("저장 경로: " + save);
int max = 1024*1024*5; // 5MB
String encoding = "utf-8";
DefaultFileRenamePolicy rename = new DefaultFileRenamePolicy();
MultipartRequest multi = new MultipartRequest(req, save, max, encoding, rename);
// ✨ 방법 1: 직접 하나씩 가져오기
String name1 = multi.getParameter("name1");
String subject1 = multi.getParameter("subject1");
String filename1 = multi.getFilesystemName("filename1");
String name2 = multi.getParameter("name2");
String subject2 = multi.getParameter("subject2");
String filename2 = multi.getFilesystemName("filename2");
String name3 = multi.getParameter("name3");
String subject3 = multi.getParameter("subject3");
String filename3 = multi.getFilesystemName("filename3");
System.out.println("파일1: " + filename1);
System.out.println("파일2: " + filename2);
System.out.println("파일3: " + filename3);
// ✨ 방법 2: Enumeration으로 모든 매개변수 확인 (디버깅용)
Enumeration keys = multi.getParameterNames();
HashMap<String,String> hm = new HashMap<String,String>();
while(keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = multi.getParameter(key);
hm.put(key, value);
System.out.println("키: " + key + ", 값: " + value);
}
// JSP로 데이터 전달
req.setAttribute("name1", name1);
req.setAttribute("subject1", subject1);
req.setAttribute("filename1", filename1);
req.setAttribute("name2", name2);
req.setAttribute("subject2", subject2);
req.setAttribute("filename2", filename2);
req.setAttribute("name3", name3);
req.setAttribute("subject3", subject3);
req.setAttribute("filename3", filename3);
RequestDispatcher ds = req.getRequestDispatcher("chapter07/fileupload02_process.jsp");
ds.forward(req, resp);
}
}
🔍 핵심 추가사항:
- 방법 1: 직접
getParameter(),getFilesystemName()하나씩 - 방법 2:
Enumeration으로 모든 매개변수 확인 (디버깅용) - HashMap: 데이터 관리 (필수는 아님)
📊 5단계: 결과 페이지에서 다중 파일 표시 ⭐⭐⭐⭐
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>다중 파일 업로드 결과</title>
</head>
<body>
<%
// ✨ 서블릿에서 전달받은 모든 데이터
String name1 = (String) request.getAttribute("name1");
String subject1 = (String) request.getAttribute("subject1");
String filename1 = (String) request.getAttribute("filename1");
String name2 = (String) request.getAttribute("name2");
String subject2 = (String) request.getAttribute("subject2");
String filename2 = (String) request.getAttribute("filename2");
String name3 = (String) request.getAttribute("name3");
String subject3 = (String) request.getAttribute("subject3");
String filename3 = (String) request.getAttribute("filename3");
%>
<h2>다중 파일 업로드 결과</h2>
<!-- ✨ 텍스트 정보 표시 -->
<h3>이름1: <%= name1 %>, 제목1: <%= subject1 %>, 파일1: <%= filename1 %></h3>
<h3>이름2: <%= name2 %>, 제목2: <%= subject2 %>, 파일2: <%= filename2 %></h3>
<h3>이름3: <%= name3 %>, 제목3: <%= subject3 %>, 파일3: <%= filename3 %></h3>
<!-- ✨ 이미지 표시 (3개 나란히) -->
<div style="display: flex; gap: 10px;">
<div>
<h4>파일 1</h4>
<img src="/JSPBook/resources/images/<%= filename1 %>" width="300" height="300">
</div>
<div>
<h4>파일 2</h4>
<img src="/JSPBook/resources/images/<%= filename2 %>" width="300" height="300">
</div>
<div>
<h4>파일 3</h4>
<img src="/JSPBook/resources/images/<%= filename3 %>" width="300" height="300">
</div>
</div>
<br><br>
<a href="exam7_2">다시 업로드하기</a>
</body>
</html>
🔍 핵심 포인트:
- 개별 처리: 각 파일을 개별적으로
request.getAttribute() - 이미지 표시:
/JSPBook/resources/images/파일명경로로 바로 접근 - 스타일:
display: flex로 3개 이미지 나란히 배치
🎯 다음에 작성할 때 순서
Step 1: 단일 파일부터
- 폼: 하나의 텍스트 + 하나의 파일
- 서블릿: MultipartRequest 기본 사용법
- 결과: 텍스트 + 이미지 1개 표시
- 테스트: 파일이
resources/images에 저장되는지 확인
Step 2: 다중 파일로 확장
- 폼: name1, name2, name3... 패턴으로 확장
- 서블릿: 개별적으로
getParameter()반복 - 결과: 여러 이미지 표시
- 테스트: 3개 파일 모두 잘 업로드되는지 확인
Step 3: 고급 기능
- Enumeration: 모든 매개변수 동적 처리
- 에러 처리: 파일 크기 초과, 빈 파일 등
- 반복문: for문으로 코드 간소화
🔄 DiskFileUpload vs MultipartRequest 비교
| 구분 | DiskFileUpload | MultipartRequest |
|---|---|---|
| 저장 위치 | C드라이브 (외부) | 웹앱 내부 |
| 이미지 표시 | ❌ (웹 접근 불가) | ✅ (바로 접근) |
| 코드 복잡도 | 복잡 (Iterator 필요) | 간단 (getParameter) |
| 파일 저장 시점 | item.write() 호출 시 |
객체 생성 시 자동 |
| 실무 용도 | 대용량, 외부 저장소 | 간단한 이미지 업로드 |
🔄 자유롭게 변경 가능한 것들
✅ 마음대로 바꿔도 되는 것:
- 서블릿 이름:
exam7_2→MultiFileUpload - 변수명:
name1, name2, name3→user1, user2, user3 - 파일 크기:
1024*1024*5→ 다른 크기 - 저장 경로:
/resources/images→/resources/uploads
❌ 정확히 써야 하는 것:
MultipartRequest생성자 5개 매개변수 순서getParameter()vsgetFilesystemName()구분request.getAttribute()와req.setAttribute()이름 일치enctype="multipart/form-data"
'JSP' 카테고리의 다른 글
| 요청->서블릿->뷰 3단계 설명 (0) | 2025.05.27 |
|---|---|
| 언제 폴더 경로를 써야 하고, 언제 안 써도 되는지 (0) | 2025.05.27 |
| DiskFileUpload 순서도 (시험 X) (0) | 2025.05.27 |
| [오류log] 서버 깨질 때 서블렛 확인할 것 (0) | 2025.05.27 |
| Enumeration 인터페이스 (0) | 2025.05.26 |