JSP 11강 - 파일 업로드, Validation

Whatever·2022년 1월 13일
0

JSP

목록 보기
11/30

* 파일 업로드란?

  • 웹 브라우저에서 서버로 파일을 전송하여 서버에 저장하는 것
  • 이미지 파일, binary 파일, 문서,텍스트 파일
  • 폼 태그 내에 사용되어야 함. 오픈 라이브러리(common-fileupload)를 사용.
  • 서버로 파일이 업로드되면? 서버는 요청 파라미터를 분석하여 파일을 찾고
    파일 저장 폴더에 저장. 이 처리는 단순한 자바 코드로 작성 불가.

파일 업로드 예제

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
<title>상품 등록</title>
</head>
<body>
<!-- top 인클루드 시작 -->
	<jsp:include page="/ch03/top.jsp" />
<!-- top 인클루드 끝 -->

<!-- content 시작 -->
	<div class="jumbotron">
		<div class="container">
			<h1 class="display-3">상품 등록</h1>
		</div>
	</div>
	<div class="container">
	<!-- addProduct_process.jsp : common-fileupload -->
	<!-- addProduct_process2.jsp : cos.jar -->
		<form name="newProduct" action="addProduct_process2.jsp" 
			method="post" class="form-horizontal"
			enctype="multipart/form-data">
			<div class="form-group row">
				<label class="col-sm-2">상품 코드</label>
				<div class="col-sm-3">
					<input type="text" name="productId" class="form-control" />
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상품명</label>
				<div class="col-sm-3">
					<input type="text" name="pname" class="form-control" />
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">가격</label>
				<div class="col-sm-3">
					<input type="text" name="uniPrice" class="form-control" />
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상세정보</label>
				<div class="col-sm-5">
					<textarea name="description" rows="2" cols="50" class="form-control"></textarea>
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">제조사</label>
				<div class="col-sm-3">
					<input type="text" name="manufacturer" class="form-control" />
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">분류</label>
				<div class="col-sm-3">
					<input type="text" name="category" class="form-control" />
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">재고 수</label>
				<div class="col-sm-3">
					<input type="text" name="unitsInStock" class="form-control" />
				</div> 
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상태</label>
				<div class="col-sm-5">
					<input type="radio" name="condition" id="condition1" value="new" />
						<label for="condition1">신규 제품</label>
					<input type="radio" name="condition" id="condition2" value="Old" />
						<label for="condition2">중고 제품</label>
					<input type="radio" name="condition" id="condition3" value="Refurbished" />
						<label for="condition3">재생 제품</label>
				</div> 
			</div>
<!-- 			<div class="form-group row"> -->
<!-- 				<label class="col-sm-2">이미지</label> -->
<!-- 				<div class="col-sm-5"> -->
<!-- 					<input type="file" name="productImage" class="form-control"/> -->
<!-- 				</div> -->
<!-- 			</div> -->
			<div class="form-group row">
				<label class="col-sm-2">이미지(cos.jar)</label>
				<div class="col-sm-5">
					<input type="file" name="productImage2" class="form-control"/>
				</div>
			</div>
			<div class="form-group row">
				<div class="col-sm-offset-2 col-sm-10">
					<input type="submit" class="btn btn-primary" value="등록" />
				</div>
			</div>
		</form>
		
	</div>

<!-- content 끝 -->
<script type="text/javascript">
CKEDITOR.replace("description")
</script>
<!-- bottom 인클루드 시작 -->
	<jsp:include page="/ch03/bottom.jsp" />
<!-- bottom 인클루드 끝 -->
</body>
</html>

방법1. commons-fileupload를 이용하여 파일 업로드하기

<%@page import="java.io.File"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="java.util.Iterator"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page import="org.apache.commons.fileupload.DiskFileUpload"%>
<%@page import="org.apache.commons.fileupload.DiskFileUpload.*"%>
<%@page import="java.util.List"%>
<!DOCTYPE html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<%
	//파일이 저장되는 경로
	String path = "C:\\upload";
	
	DiskFileUpload upload = new DiskFileUpload();
	//업로드할 파일의 최대 크기(1M) 
	upload.setSizeMax(1000000);
	//메모리상에 저장할 최대 크기
	upload.setSizeThreshold(4096);
	//업로드된 파일을 임시 저장
	upload.setRepositoryPath(path);
	//파싱 : 구문분석 + 의미분석
	//items 안에는 파일객체 + 폼 데이터가 섞여있음
	List items = upload.parseRequest(request);
	
	Iterator params = items.iterator();
	//폼 페이지에서 전송된 요청 파라미터가 없을 때까지 반복
	while(params.hasNext()){
		//전송된 요청 파라미터의 이름을 가져오도록 Iterator 객체 타입의 
		//next() 메소드 사용
		FileItem item = (FileItem)params.next();
		
		if(item.isFormField()){ //요청 파라미터가 일반 데이터(text, checkbox, radio..)
			//?id=a001
			String name = item.getFieldName(); //id
			String value = item.getString("UTF-8"); //a001
			out.print(name = "=" + value +"<br />");
		}else{ //폼 페이지에서 전송된 요청 파라미터가 파일(input type='file')
			//요청 파라미터의 이름
			String fileFieldName = item.getFieldName();
			//저장 파일 이름
			String fileName = item.getName();
			//파일 콘텐츠 유형
			String contentType = item.getContentType();
			
			out.print(fileFieldName + "=" + fileName +"(" + contentType +")");
			//경로에서 파일 이름만 가져오기
			//켄싱.jpg가 됨
			fileName.substring(fileName.lastIndexOf("\\") + 1);
			long fileSize = item.getSize();
			//java.io.file => 파일 객체 생성
			File file = new File(path + "/" + fileName);
			//여기서 실제로 파일 생성(복사 완료)
			item.write(file);
			
			
		}
	}
%>
</body>
</html>

request.getParameter 사용불가능

방법2. cos.jar를 이용하여 파일 업로드하기

request.getParameter로 파라미터를 바로 가져올 수 있다.

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@page import="dto.Product"%>
<%@page import="ch04.com.dao.ProductRepository"%>
<%@page import="java.util.Enumeration"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>

<%
	request.setCharacterEncoding("UTF-8");
	//웹 어플리케이션상의 절대 경로
	String realFolder = "D:\\A_TeachingMaterial\\6.JspSpring\\workspace\\JSPBook\\WebContent\\upload";
	
	String filename = "";
	//최대 업로드될 파일의 크기 5MB
	int maxSize = 5*1024*1024;
	//인코딩 유형
	String encType = "UTF-8";
	
	//
	MultipartRequest multi = new MultipartRequest(
			request, realFolder, 
			maxSize, encType,
			new DefaultFileRenamePolicy()
			);
	//request객체, 저장될 실제 경로, 저장될 최대 크기, encType, 기본 파일정책
	//request객체가 multi 안에 들어있기 때문에 request.getParameter와 같다고 봐도 됨.
	String productId = multi.getParameter("productId"); 
	String pname = multi.getParameter("pname"); 
	String uniPrice = multi.getParameter("uniPrice"); 
	String description = multi.getParameter("description"); 
	String manufacturer = multi.getParameter("manufacturer"); 
	String category = multi.getParameter("category"); 
	String unitsInStock = multi.getParameter("unitsInStock"); 
	String condition = multi.getParameter("condition"); 
	
	/* uniPrice가 비어있을 때 */
	Integer price;
	if(uniPrice.isEmpty()){
		price = 0;
	}else{
		//"1000000" -> 1000000
		price = Integer.valueOf(uniPrice);
	}
	
	/* unitsInStock가 비어있을 때 */
	long stock;
	if(unitsInStock.isEmpty()){
		stock = 0;
	}else{
		stock = Long.valueOf(unitsInStock);
	}
	
	//파일객체 처리
	//multi객체 안에는 request 객체가 들어있고, request객체 안에는 파일객체가 있음
	Enumeration files = multi.getFileNames();
	//productImage2
	String fname = (String)files.nextElement();
	//폼 페이지에서 전송되어 서버에 업로드된 파일을 가져옴
	//P1237.jpg
	String fileName = multi.getFilesystemName(fname);
	
	out.print("fname : " + fname + ", fileName : " + fileName);
	
	ProductRepository dao = ProductRepository.getInstance();
	
	Product newProduct = new Product(); //그릇 
	newProduct.setProductId(productId);
	newProduct.setPname(pname);
	newProduct.setDescription(description);
		newProduct.setUniPrice(price);
	newProduct.setManufacturer(manufacturer);
	newProduct.setCategory(category);
		newProduct.setUnitsInStock(stock);
	newProduct.setCondition(condition);
	//파일 객체의 파일명
	newProduct.setFilename(fileName);
	//dao : data access object(여기서는 메모리 DB라고 생각)
	dao.addProduct(newProduct); //insert
	//상품 목록으로 리다이렉트
	response.sendRedirect("products.jsp");
%>

</body>
</html>

[정리]

1. 파일 업로드란?

  • 웹 브라우저(크롬)에서 서버(톰캣 포함)로 파일을 전송하여 저장하는 것.
  • 웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그 사용
  • 전송된 파일을 서버에 저장하기 위해 오픈 라이브러리(common-fileupload, cos.jar)를 이용함

2. cos.jar

  • cos.jar의 핵심 클래스는 MultipartRequest 이다.
  • MultipartRequest 클래스를 통해 객체를 생성하고 해당 객체의 메소드들을 활용하여 웹 브라우저(크롬)가 전송한 multipart/form-data 유형의 요청 파라미터를 읽어오고 파일을 업로드함.

3. Commons-FileUpload

  • 먼저 Commons-FileUpload 패키지에 포함되어 있는 DiskFileUpload 클래스를 통해 객체를 생성
  • 생성된 객체의 메소드들을 사용하여 웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 가져옴
  • FileItem 클래스의 메소드를 사용하여 요청 파라미터가 일반 데이터인지 파일인지 분석 및 처리하여 파일을 업로드함

Validation

유효성 검사

1. 유효성 검사란?

  • 폼 페이지에서 입력한 데이터 값이 서버로 전송되기 전에 특정 규칙에 맞게 입력되었는지 검증하는 것
  • 예) 나이 입력 시 숫자 체킹, 회원가입 시 아이디 중복 체크, 로그인 인증 시 아이디와 비밀번호를 체킹 등

2. 핸들러 함수란?

  • 폼 페이지에서 이벤트 발생 시 유효성 검사를 위해 매핑하는 메소드로, Javascript/JQuery를 이용하여 유효성 검사를 하는 코드의 집합.
  • 서버에 과부하를 주지 않음

3. 유효성 검사의 종류

  • 기본 유효성 검사 : 값의 존재 유무
  • 데이터 형식 유효성 검사 : 패턴에 적합한지 여부(정규 표현식 사용)

4. 기타

  • isNaN() : is Not a Number => 숫자 false, 숫자가 아니면 true

5. 정규 표현식(암기법 : 정규 표현식 썼어? 이긍..)

  • 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식의 언어
  • 문자열의 특정 형태를 찾아내기 위해 일정한 형식의 패턴으로 표현
  • 예) 주민등록번호, 전화번호, 이메일
  • var 변수명 = /정규 표현식/[Flag];
  • var 변수명 = new RegExp('정규 표현식',[Flag]);
  • Flag란?
    - i : ignore case(문자열의 대문자와 소문자를 구별하지 않고 검출)
    - g : global(문자열 내의 모든 패턴을 검출)
    - m : multi line(문자열에 줄 바꿈 행이 있는지 검출)
  • [Flag]는 생략 가능. 만약 생략했다면.. 한 번만 검출
  • 정규 표현식 메소드
    - test() : 문자열이 정규 표현식에 부합한지 판단(true/false 반환)
    - exec() : 문자열에서 정규 표현식에 부합된 문자열을 추출하여 반환
    실행 결과 :

  • 정규표현식에서 사용하는 기호(메타 문자) - 특정한 의미를 가진 문자
    - ^x : 문자열이 x로 시작
    - x$ : 문자열이 x로 종료
    - .x : (임의의 한 문자) 문자열이 x로 끝남
    - x+ : x가 한 번 이상 반복
    - x? : x가 없다
    - x* : x가 0번 이상 반복
    - x|y : (or)x또는 y를 찾음
    - (x) : ( )안의 내용을 그룹화
    - (x)(y) : 그룹화. 자동 그룹번호 부여 => 배열
    - x{n} : x를 n번 반복한 문자를 찾음
    - x{n,} : x를 n번 이상 반복한 문자를 찾음
    - x{n,m} : x를 n번 이상 m번 이하 반복한 문자를 찾음
    - [xy] : x 또는 y를 찾음
    - [^xy] : x,y를 제외하고 문자 하나를 찾음
    - [x-z] : x부터 z사이의 문자 중 하나를 찾음

[숙제]

  1. 파일 업로드를 위한 form태그 내에 반드시 설정해야 하는 기법은 무엇인가?
    => enctype="multipart/form-data"

  2. 파일을 서버에 업로드하는 처리 기법에 대해 간단히 설명하시오
    => cos.jar와 commons-fileupload 두 가지가 있다.

  3. MultipartRequest 클래스를 이용하여 다음 조건에 맞게 JSP 애플리케이션을 만들고 실행 결과를 확인하시오.

6. 데이터 형식 유효성 검사

  • 사용자가 폼 페이지 입력 항목에 입력한 데이터 값이 특정 형태에 적합한지 검사하기 위해 정규 표현식을 사용하는 방법
  • 특정한 규칙을 가진 문자열의 집합을 표현하는데 사용하는 형식 언어
  • 정규 표현식(regExp)에서 사용하는 기호를 메타 문자라고 함
  • 메타 문자는 정규 표현식 내부에서 특정한 의미를 가진 문자

0개의 댓글