티스토리 뷰

코딩/JSP

[9주 4일차] 파일 업로드

ehzim 2023. 12. 7. 17:58

Chpater7.파일 업로드 

 

 

 

 

1. 파일 업로드의 개요

 

웹 브라우저에서 서버로 파일을 전송하여 서버에 저장한다.

서버에 업로드할 수 잇는 파일은 텍스트, 바이너리, 이미지, 문서 등이 있다.

웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 사용하고 전송된 파일은 서버에 저장하기 위해 오픈 라이브러리를 이용해야한다.

 

 

 

 

 

1.1 파일 업로드를 위한 JSP 페이지

 

<form action="JSP 파일" method="post" enctype="multipart/form-data">
	<input type="file" name="요청 파라미터 이름">
</form>

 

위의 코드는 파일 업로드를 위한 코드 형식이다.

이때 method="post" enctype="multipart/form-data" 와 input의 타입은 file로 지정을 필수적으로 해주어야한다.

method에서 post를 사용하는 이유는 get 은 용량이 정해져있기 때문에 post를 사용한다.

multipart 또한 필수적으로 들어가야하는 옵션인데 

파일 업로드시 text와 image 등 여러개의 데이터를 다룬다.

여러개의 데이터를 사용하기 위해 multipart를 사용한다.

 

 

 

1.2 파일 업로드 처리 방법

 

웹 브라우저에서 서버로 파일을 업로드하면 서버는 요청 파라미터를 분석하여 파일을 찾고 서버의 자원에 저장하는 과정을 거친다.

파일 업로드 처리는 자바 코드로 작성해서 처리할 수 없기 때문에 오픈 라이브러리인 cos.jar 이나 commons-fileupload.jar를 사용해야 한다.

 

 

종류 특징 필요한 라이브러리
MultipartRequest 이용하기 가장 간단한 방법 cos.jar
아파치 APR 이용하기 편리하고 강력한 API 제공한다. commons-fileupload.jar
commons-io.jar

 

 

 

 

2. MultipartRequest를 이용한 파일 업로드

 

MultipartRequest는 웹 페이지에서 서버로 업로드되는 파일 자체만 다루는 클래스이다.

역시나 method="post" enctype="multipart/form-data"를 사용해야한다.

 

 

 

 

 

 

2.1 MultipartRequest 클래스 생성

 

 

MultipartRequest(javax.sevlet.http.HttpServletRequest request, java.lang.String saveDirectory,
				int maxPostsize, java.lang.String encoding, FileRenamePolicy policy)

 

생성자(객체,String,정수,String,객체)

 

 

 

MultiparRequest 생성자의 매개변수

매개변수 설명
request Request 내장 객체를 설정한다. (객체)
saveDirectory 서버의 파일 저장 경로를 설정한다. (문자열)
maxPostSize 파일의 최대 크기(바이트 단위)를 설정한다. 최대 크기를 초과하면 IOEception이 발생한다. (정수)
encoding 인코딩 유형을 설정한다. (문자열)
policy 파일명 변경 정책을 설정한다. saveDirectory에 파일명이 중복되는 경우 덮어쓰기 여부를 설정한다.
설정하지 않으면 덮어쓴다. (객체)

 

 

ex) MultipartRequest 클래스 생성 예

 

<%@ page import="com.oreilly.servlet.*"%>
<%@ page import="com.oreilly.servlet.multipart.*"%>
...(생략)...
MultipartRequest multi = new MultipartRequest(request,"C:\\upload", 5*1024*1024, "utf-8",new DefaultFileRenamePolicy())

 

C:\\upload 는 저장하는 경로를 말해준다.(=saveDirectory)

5*1024*1024 는 파일 최대 크기는 5MB (5X1,024X1,024B)이다.

파일명의 인코딩 유형은 utf-8 로 설정되었다.

서버에 저장된 파일명 중복을 처리하기 위해 DefaultFileRenamePolicy 클래스를 사용한다.

 

 

 

 

 

2.2 MultipartRequest 메소드

 

 

 

MultipartRequest 메소드의 종류

메소드 유형 설명
getContentType(String name) String 업로드된 파일의 콘텐츠 유형을 반환한다.
업로드된 파일이 없으면 null을 반환한다.
getParameter(String name) String 요청 파라미터 이름이 name인 값을 전달 받는다.
(text 데이터)
(수동 방식)
getParameterNames() java.util.Enumeration 요청 파라미터 이름을 Enumeration 객체 타입으로 반환한다.
(Enumeration은 while사용해서 객체 저장 및 출력)
(text keys만)
(자동 방식)
getFile(String name) java.io.File 서버에 업로드된 파일에 대한 파일 객체를 반환한다.
업로드된 파일이 없으면 null을 반환한다.
getFileNames() java.util.Enumeration 폼 페이지에 input태그 내 type 속성값이 fil로 설정된 요청 파라미터의 이름을 반환한다.
(while을 사용해서 저장 및 출력)
(image keys 만)
(자동 방식)
getFilesystemName(String name) String 사용자가 설정해서 서버에 실제로 업로드된 파일명을 반환한다.
파일명이 중복되면 변경된 파일명을 반환한다.
(이미지 이름 데이터)
(수동 방식)
getOriginalFielName(String name) String 사용자가 업로드한 실제 파일명을 반환한다.
파일명이 중복되면 변경 전의 파일명을 반환한다.
(이미지 이름 데이터)
(수동 방식)

 

 

 

 

 

 

ex) MultipartRequest 클래스를 이용하여 파일 업로드 및 정보 출력

예제 7-1

 

fileupload01.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>
	<form name="filename" method="post" enctype="multipart/form-data" action="fileupload01_process.jsp">
		<p>이 름 : <input type="text" name="name">
		<p>제 목 : <input type="text" name="subject">
		<p>파 일 : <input type="file" name="filename">
		<p> <input type="submit" value="파일 올리기">
	</form>
</body>
</html>

 

웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 사용했다.

폼의 이름은 filename으로 지정하고 method형식과 ectype은 앞서 말한 것과 같이 post, multipart/form-data로 지정하였다.

action은 process와 연결하여 submit하면 process가 실행될 수 있도록 했다.

 

 

 

 

fileupload01_process.jps

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="com.oreilly.servlet.*" %>    
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	
	MultipartRequest multi = new MultipartRequest(request, "c:\\ltr", 5*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	
	/*String name = multi.getParameter("name");
	  out.println("name + " = " + value + "<br>");
	  String subject = multi.getParameter("subject");
	  out.println("subject + " = " + value + "<br>");*/

	Enumeration params = multi.getParameterNames();
	
	while(params.hasMoreElements()){
		String name=(String) params.nextElement();
		String value = multi.getParameter(name);
		out.println(name + " = " + value + "<br>");
	}
	out.println("-------------------<br>");
	
	/*String filename=multi.getFile("filename");
	  String filename=mult.getFilesystemName(filename);
	  String original = multi.getOriginalFileName(filename);
	  String type = multi.getContentType(name);
	  File file = multi.getFile(name); */
	  
	  
	Enumeration files = multi.getFileNames();
	
	while(files.hasMoreElements()){
		String name = (String) files.nextElement();
		String filename = multi.getFilesystemName(name);
		String original = multi.getOriginalFileName(name);
		String type = multi.getContentType(name);
		File file = multi.getFile(name); 
		

		
		out.println("요청 파라미터 이름 : "+ name + "<br>");
		out.println("실제 파일 이름 : "+original + "<br>");
		out.println("저장 파일 이름 : " + filename + "<br>");
		out.println("파일 콘텐츠 유형 : " + type + "<br>");
		
		if (file != null){
			out.println(" 파일 크기 : " +file.length());
			out.println("<br>");
		}
	}
%>	
</body>
</html>

 

첫번쨰로 multi라는 객체를 생성해 주었다.

파일 경로를 C:\\ltr로 지정하고 크기는 5MB, 인코딩 유형은 utf-8, 파일명이 중복되지 않도록 DefaultRileRenamePolicy클래스로 작성해주었다.

Enumeration을 사용하여 자동방식으로 작성한 것을 알 수 있다.

그리고 Enumeration을 사용했기 떄문에 while을 사용하여 파일을 가져오도록 해주었다.

 

저장된 파일을 불러올 때 코드를 보면 (String)으로 캐스팅한 것을 볼 수 있다.

이때 캐스팅을 하는 이유는 파일을 불러오는 과정에 있다.

request에 저장된 것을 불러오기 때문인데 request에 저장시 문자열로 저장되기 때문에 String으로 캐스팅해주어야한다.

 

 

 

 

결과

fileupload01을 실행하면 위와 같은 실행 창이 뜬다.

이름과 제목 파일에 각각 이름과 파일을 입력한 후 submit 버튼인 파일 올리기를 클릭한다.

 

클릭한 후 위와 같은 창이 나타나는데

그 이유는 fileupload01에서 submit하면 process로 이동하도록 action줬기 때문이다.

그러므로 파일이 저장되고 process가 실행되어 파라미터 이름 파일 이름 등을 출력한다. 

 

 

저장 경로인 ltr로 들어가 확인하면 제대로 저장된 것을 확인 할 수 있다.

 

 

 

 

 

 

 

img파일 만들기

 

: 파일 업로드 및 정보 출력을 다른 방식으로 해보았다.

 

 

img 폴더에 저장하는 것을 알기 위해 먼저 webapp 폴더 안에 img 폴더를 만들어주었다.

 

 

 

파일 저장 경로를 기존의 C가 아닌 img 로 설정하여 save 함수에 담아주고 save를 저장 경로로 지정해주었다.

 

 

첫번째 방법과 동일하게 파일을 업로드 시킨 것을 확인했다.

 

 

 

console 창에 파일이 업로드된 정확한 위치가 표기되어 위치를 확인할 수 있었다.

그 위치를 가지고 파일 탐색기에 검색하여 확인하면 정상적으로 저장된 것을 확인할 수 있다.

 

 

 

 

 

 

- 이미지를 웹 브라우저에 직접적으로 출력하는 방식

 

 

out.println("<img src=./img/" + filename + ">"); 코드를 작성하여

img 파일을 출력하는 코드를 추가해주었다.

 

 

 

추가한 후 실행하면 웹브라우저에 이미지 파일로 함께 출력되는 것을 확인할 수 있다.

 

 

 

출력한 후 out.print에 대한 이해를 높이기 위해 F12를 눌려 network를 확인해보았다.

 

F12번 결과

response 탭을 확인하면 jsp에서 out.print로 작성한 코드들이 html로 저장된 것을 볼 수 있다.

out.print는 실행하여 html로 한줄씩 response에 저장된다는 것을 이해할 수 있었다.

 

 

 

 

 

 

submit할 경우 html과 연결하는 방법

 

 

먼저 html 파일을 작성해주었다.

 

 

String 타입으로로 각각 값들을 저장해준 후 출력하는 것이 아니라 이전에 작성한 out.html 을 실행하도록 코드를 작성했다.

response.senRedirect("이동할 페이지");

 

(sendRedirect는 while 밖에 잇어야함 안에 있어도 파일은 하나라서 한번만 실행하긴 함.)

 

값들을 입력한 후 submit을 하면 연결한 html 파일로 이동하여 html 파일이 실행된 것을 볼 수 있었다.

 

 

 

 

 

 

ex) MultiparRequest 클래스를 이용하여 여러 파일 업로드 및 정보 출력하기

 

예제 7-2

 

fileupload02.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>
	<form name="fileForm" method="post" enctype="multipart/form-data" action="fileupload02_process.jsp">
		<p> 이 름1 : <input type="text" name="name1">
			제 목1 : <input type="text" name="subject1">
			파 일1 : <input type="file" name="filename1">
		<p> 이 름2 : <input type="text" name="name2">
			제 목2 : <input type="text" name="subject2">
			파 일2 : <input type="file" name="filename2">
		<p> 이 름3 : <input type="text" name="name3">
			제 목3 : <input type="text" name="subject3">
			파 일3 : <input type="file" name="filename3">
		<p> <input type="submit" value="파일 올리기">	
	</form>
</body>
</html>

 

예제 7-1에서는 하나의 파일만 다루었다면 7-2에서는 여러개의 파일을 다루었다.

이전과 같이 process와 연결해주고 method, enctype을 설정해주었다.

파일의 이름과 제목 파일을 입력 받아 submit 하는 코드를 작성했다.

 

 

 

 

 

fileupload02_process.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="com.oreilly.servlet.*" %>    
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		String save = request.getServletContext().getRealPath("/img");
		MultipartRequest multi = new MultipartRequest(request, save, 5*1024*1024, "utf-8", new DefaultFileRenamePolicy());
		
		String name1 = multi.getParameter("name1");
		String subject1 = multi.getParameter("subject1");
		
		String name2 = multi.getParameter("name2");
		String subject2 = multi.getParameter("subject2");
		
		String name3 = multi.getParameter("name3");
		String subject3 = multi.getParameter("subject3");
		
        
		Enumeration files = multi.getFileNames();
			
		String file3 = (String) files.nextElement();
		String filename3 = multi.getFilesystemName(file3);
		
		String file2 = (String)files.nextElement();
		String filename2 = multi.getFilesystemName(file2);
		
		String file1 = (String)files.nextElement();
		String filename1 = multi.getFilesystemName(file1);
		
	%>
	
	<table border="1">
		<tr>
			<th width="100">이름</th>
			<th width="100">제목</th>
			<th width="100">파일</th>
		</tr>
		<%
			out.print("<tr><td>" + name1 + "</td>");
			out.print("<td>" + subject1 + "</td>");
			out.println("<td>" + filename1 + "</td></tr>\n");
			
			out.print("<tr><td>" + name2 + "</td>");
			out.print("<td>" + subject2 + "</td>");
			out.println("<td>" + filename2 + "</td></tr>\n");
			
			out.print("<tr><td>" + name3 + "</td>");
			out.print("<td>" + subject3 + "</td>");
			out.println("<td>" + filename3 + "</td></tr>\n");
			
		%>	
	</table>
</body>
</html>

 

경로 지정 및 파일 크기 인코딩 유형 등을 먼저 설정해주었다.

파일 저장하는 방식은 텍스트는 수동 저장 방식을 사용하고 이미지 파일은 자동 저장 방식을 사용했다.

수동 저장 방식은 하나씩 수동으로 저장되기 때문에 불러와 저장하는 순서대로 저장된다.

하지만 자동 저장 방식은 자동으로 저장되는데 스택구조를 가지고 있기 때문에 제일 나중에 저장한 데이터부터 출력된다.

그렇기때문에 3번부터 1번까지 역순으로 저장해주었다.

 

테이블을 만들어 변수에 저장된 값들을 테이블에 출력해주었다.

 

* 스택 구조

LIFO형식을 사용하는 자료 구조로 가장 최근에 들어온 데이터가 가장 먼저 나간다.(후입선출)

 

 

 

 

결과

 

여러개의 파일을 submit해주었다.

 

 

submit된 후 process에서 작성한 코드와 같이 테이블이 작성된 것을 볼 수 있다.

'코딩 > JSP' 카테고리의 다른 글

[9주 5일차] 파일 업로드 (2)  (1) 2023.12.08
웹쇼핑몰  (1) 2023.12.08
[9주 4일차] 웹 쇼핑몰 : 상품 등록 페이지 만들기  (1) 2023.12.07
[9주 3일차] 폼 태그  (1) 2023.12.06
[9주 3일차] 내장 객체 2  (2) 2023.12.06
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday