📚 기본 이해: What & Why
전체 흐름:
사용자 → 폼(JSP) → 서블릿 → 결과페이지(JSP)
Why 파일 업로드가 특별한가?
- 일반 텍스트:
application/x-www-form-urlencoded - 파일 업로드:
multipart/form-data(특별한 형식 필요) - DiskFileUpload: C드라이브 같은 외부 디스크에 저장하는 실무 방식
🚀 1단계: 가장 기본 폼부터 ⭐
Why 폼부터?
가장 쉽고, 눈으로 바로 확인 가능
<%@ 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" action="fileupload">
<p> 이름: <input type="text" name="name">
<p> 파일: <input type="file" name="filename">
<p> <input type="submit" value="업로드">
</form>
</body>
</html>
🔍 핵심 포인트:
action="fileupload"← 서블릿 이름 (자유롭게 변경 가능)name="filename"← 변수명 (자유롭게 변경 가능)- 아직
enctype없음 ← 나중에 추가할 예정
🛠️ 2단계: 서블릿 뼈대만 ⭐⭐
Why 뼈대부터?
복잡한 파일 처리 말고, 일단 폼과 연결되는지 확인
package fileupload;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.*;
@WebServlet("/fileupload") // ← URL 패턴 (자유롭게 변경 가능)
public class FileUploadServlet extends HttpServlet { // ← 클래스명 (자유롭게 변경 가능)
// GET: 폼 페이지 보여주기
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
RequestDispatcher dispatcher = req.getRequestDispatcher("fileupload.jsp");
dispatcher.forward(req, resp);
}
// POST: 데이터 받기 (일단 간단하게)
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8"); // 한글 깨짐 방지
// 테스트용: 텍스트만 받아보기
String name = req.getParameter("name");
req.setAttribute("message", "안녕하세요 " + name + "님!");
RequestDispatcher dispatcher = req.getRequestDispatcher("result.jsp");
dispatcher.forward(req, resp);
}
}
🔍 핵심 포인트:
- doGet: 폼 보여주는 역할
- doPost: 데이터 받는 역할
- 아직 파일 처리 없음 ← 나중에 추가
📄 3단계: 결과 페이지 (간단 버전) ⭐
Why 간단 버전부터?
서블릿에서 데이터가 잘 넘어오는지 확인
<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>업로드 결과</title>
</head>
<body>
<h2>결과 확인</h2>
<%
String message = (String) request.getAttribute("message");
if(message != null) {
out.println(message);
}
%>
<br><br>
<a href="fileupload">다시 해보기</a>
</body>
</html>
🔍 핵심 포인트:
request.getAttribute("message")← 서블릿에서 보낸 데이터 받기- 서블릿 ↔ JSP 연결 확인
⚡ 4단계: 파일 업로드 추가 ⭐⭐⭐
Why 이제 파일?
기본 연결이 되면 이제 파일 처리 추가
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="fileupload">
<p> 이름: <input type="text" name="name">
<p> 파일: <input type="file" name="filename">
<p> <input type="submit" value="업로드">
</form>
</body>
</html>
🔍 변경사항:
enctype="multipart/form-data"← 필수! 파일 업로드용
4-2: 서블릿에 파일 처리 추가
package fileupload;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.*;
import java.util.*; // ✨ 추가
import org.apache.commons.fileupload.*; // ✨ 추가
@WebServlet("/fileupload")
public class FileUploadServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
RequestDispatcher dispatcher = req.getRequestDispatcher("fileupload.jsp");
dispatcher.forward(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
// ✨ 여기부터 파일 처리 추가!
String path = "C:\\upload"; // 저장할 폴더 (자유롭게 변경 가능)
// 폴더 생성
File uploadDir = new File(path);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// DiskFileUpload 설정
DiskFileUpload upload = new DiskFileUpload();
upload.setSizeMax(1000000); // 최대 크기 1MB (변경 가능)
upload.setSizeThreshold(4096); // 메모리 임계값 (변경 가능)
upload.setRepositoryPath(path);
try {
List items = upload.parseRequest(req); // 파일 받기
req.setAttribute("items", items);
req.setAttribute("uploadPath", path);
} catch(Exception e) {
req.setAttribute("error", e.getMessage());
}
RequestDispatcher dispatcher = req.getRequestDispatcher("result.jsp");
dispatcher.forward(req, resp);
}
}
🔍 핵심 추가사항:
import두 개 추가- C드라이브 폴더 생성 로직
- DiskFileUpload 설정 및 파일 받기
📊 5단계: 결과 페이지에서 파일 정보 표시 ⭐⭐⭐⭐
Why 복잡해보이나?
파일과 텍스트가 섞여서 와서 구분해서 처리해야 함
<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="org.apache.commons.fileupload.*" %> <!-- ✨ 추가 -->
<%@ page import="java.io.*" %> <!-- ✨ 추가 -->
<%@ page import="java.util.*" %> <!-- ✨ 추가 -->
<html>
<head>
<title>업로드 결과</title>
</head>
<body>
<h2>업로드 결과</h2>
<%
// 1단계: 서블릿에서 데이터 받기
List items = (List) request.getAttribute("items");
String path = (String) request.getAttribute("uploadPath");
String error = (String) request.getAttribute("error");
// 2단계: 에러 체크
if(error != null) {
out.println("오류: " + error);
} else if(items != null) {
// 3단계: 파일 목록을 하나씩 처리
Iterator params = items.iterator();
while (params.hasNext()) {
FileItem item = (FileItem) params.next();
// 4단계: 텍스트 vs 파일 구분
if (item.isFormField()) {
// 텍스트 필드 (이름 등)
String name = item.getFieldName();
String value = item.getString("utf-8");
out.println(name + " = " + value + "<br>");
} else {
// 파일 필드
String fileFieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
if(fileName != null && !fileName.equals("")) {
// 5단계: 파일명 정리 (경로 제거)
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
long fileSize = item.getSize();
// 6단계: 실제 파일 저장
File file = new File(path + "/" + fileName);
item.write(file);
// 7단계: 결과 출력
out.println("------------------------------------------<br>");
out.println("요청 파라미터 이름 : " + fileFieldName + "<br>");
out.println("저장 파일 이름 : " + fileName + "<br>");
out.println("파일 콘텐츠 유형 : " + contentType + "<br>");
out.println("파일 크기 : " + fileSize + "<br>");
out.println("C드라이브 저장 완료: " + path + "/" + fileName);
}
}
}
}
%>
<br><br>
<a href="fileupload">다시 업로드하기</a>
</body>
</html>
🔍 단계별 이해:
- 데이터 받기: 서블릿에서 보낸
items,path,error받기 - 에러 체크: 문제 있으면 에러 메시지 출력
- 반복 처리:
Iterator로 업로드된 항목들 하나씩 처리 - 구분 처리: 텍스트(
isFormField())와 파일 구분 - 파일명 정리: Windows 경로 제거
- 실제 저장:
item.write(file)로 C드라이브에 저장 - 결과 출력: 파일 정보 화면에 표시
🎯 다음에 작성할 때 순서
Step 1: 기본 연결부터 확인
- 폼 (파일 업로드 설정 없이)
- 서블릿 뼈대 (파일 처리 없이)
- 결과 페이지 (간단하게)
- 테스트: 텍스트만 잘 전달되는지 확인
Step 2: 파일 업로드 추가
- 폼에
enctype="multipart/form-data"추가 - 서블릿에
DiskFileUpload추가 - 결과 페이지에 파일 처리 로직 추가
- 테스트: C드라이브에 파일이 저장되는지 확인
Step 3: 완성도 높이기
- 에러 처리 강화
- 파일 크기 제한
- 이미지만 업로드 가능하게 등
🔄 자유롭게 변경 가능한 것들
✅ 마음대로 바꿔도 되는 것:
- 서블릿 이름:
fileupload→FileUpload - 클래스명:
FileUploadServlet→UploadHandler - 변수명:
name,filename→userName,uploadFile - 폴더 경로:
C:\upload→D:\myfiles - 파일 크기:
setSizeMax(1000000)→ 다른 크기
❌ 정확히 써야 하는 것:
enctype="multipart/form-data"DiskFileUpload클래스명parseRequest(),write()메서드명@WebServlet형식request.getAttribute()와req.setAttribute()이름 일치
🚨 자주 하는 실수들
1. enctype 빼먹기
<!-- ❌ 틀림 -->
<form method="post" action="fileupload">
<!-- ✅ 맞음 -->
<form method="post" enctype="multipart/form-data" action="fileupload">
2. import 빼먹기
// ❌ 이것들 없으면 에러
import org.apache.commons.fileupload.*;
import java.util.*;
3. 폴더 생성 안하기
// ✅ 폴더 없으면 만들어주기
File uploadDir = new File(path);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}'JSP' 카테고리의 다른 글
| 언제 폴더 경로를 써야 하고, 언제 안 써도 되는지 (0) | 2025.05.27 |
|---|---|
| MultipartRequest (0) | 2025.05.27 |
| [오류log] 서버 깨질 때 서블렛 확인할 것 (0) | 2025.05.27 |
| Enumeration 인터페이스 (0) | 2025.05.26 |
| 외부입력 필요/없어도 될 때 (0) | 2025.05.26 |