ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [jsp] 파일 업로드
    jsp 2023. 4. 25. 18:41

    파일 업로드는

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

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

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

     

    웹 브라우저에서 서버로 파일을 전송하기 위해서는 jsp 페이지에 폼 태그를 작성할떄 몇가지 중요한 규칙을 따라야한다.

    1. form 태그의 method 속성은 반드시 post로 설정

    2. form 태그의 enctype 속성은 반드시 multipart/form-data로 설정

    3. form 태그의 action 속성은 파일 업로드를 처리할 jsp 파일로 설정

    4. 파일 업로드를 위해 input태그의 type속성은 "file"로 설정, 여러 파일을 업로드하려면 2개이상의 input 태그를 사용하고 name속성에 서로 다른값 설정

    <form action="process.jsp" method="post" enctype="multipart/form-data">
    	<input type="file" name="fileName1">
    </form>

    파일 업로드 처리 방법

    1. 웹 브라우저에서 서버로 파일을 업로드하면,

    2. 서버는 요청 파라미터를 분석하여 파일을 찾고

    3. 서버의 자원에 저장하는 과정을 거친다. 

     

    이러한 파일 업로드의 처리는 단순한 자바 코드로 작성하여 처리할 수 없어 cos.jar(MultipartRequest) 혹은 commons-fileupload.jar(아파치API) 등을 사용해야 한다.

    MultipartReqeust를 이용한 파일 업로드

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

    웹 브라우저가 전송한 multipart/form-data 유형과 post방식의 요청 파라미터 등을 분석한 후 , 일반 데이터와 파일 데이터를 구분하여 파일 데이터에 접근한다.

    또한 한글 인코딩 값을 얻기 쉽고, 서버의 파일 저장 폴더에 동일한 파일명이 있으면 파일명을 자동으로 변경하는 등 유용하다.

     

    MultipartReqeusts는 cos 패키지에 포함되어 있는 파일 업로드 컴포넌트이다.사용하기 위해서는 cos.jar 설치 -> /WebContent/WEB-INF/lib/ 폴더에 위치 ->  <%@ page import="com.oreilly.servlet.*  %>설정해야함

     

    MultipartRequest 클래스를 이용하여 파일을 업로드하려면 먼저 MultipartRequest 객체를 생성해야한다.

    그리고 생성된 객체를 통해 MultipartRequest 클래스가 제공하는 메소드를 사용하여, 웹 브라우저가 전송한 multipart/form-data 유형의 요청파라미터를 읽어오고 파일을 업로드한다.

     

    MultipartRequest 클래스 생성

    MultipartReqeust 클래스는 다양한 생성자를 제공한다.

    그 중 한글 인코딩 값을 쉽게 얻을 수 있고, 업로드되는 파일이 서버에 저장된 기존 파일과 중복될 떄 자동으로 변경해주는 생성자의 형식은 다음과 같다

    MultipartReqeust(javax.servlet.http.HttpServletRequest request,
    	java.lang.String saveDirectory,
        int maxPortSize,
        java.lang.String encoding,
        FileRenamePolicy policy)
    request : Request내장객체 설정
    saveDirectory : 서버의 파일 저장 경로 설정
    maxPortSize : 파일의 최대크기 설정, 최대 크기 초과하면 예외처리 발생
    encoding : 인코딩 유형 설정
    policy : 파일명 정책 설정. saveDirectroy에 파일명이 중복되는 경우 덮어쓰기 여부 설정, 설정하지않으면 덮어씀

     

    다음 예제는 MultipartRequest 클래스를 생성하는 예시이다.

    웹 브라우저에서 전송되는 파일을 서버의 C:|upload| 경로에 저장, 파일 크기는 5MB(5*1024*1024B), 파일 인코딩 유형은 utf-8, 서버에 저장된 파일명 중복을 처리하기 위해 DefalutFileRenamePloicy 사용 : 동일한 파일이존재하면 전송된 파일명 뒤에 숫자를 덧붙여 파일명이 중복되지 않도록 함, 사용하기위해 com.oreilly.servlet.mulitpart.* 설정 필요

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

    MultipartRequest 메소드

    웹 브라우저에서 전송한 multipart/form-data 유형의 요청 파라미터를 쉽게 읽어오고 , 파일을 업로드할 수 있도록 MultipartRequest클래스에는 다양한 메소드가 있다.

    일반 데이터는 getParameter()를 사용해 값을 받을 수 있던걸 기억해보자, 파일의 경우 getFileNames()메소드를 이용하여 데이터를 받는다.

    getContentType(String name) : 업로드된 파일의 콘텐츠 유형을 반환한다. 업로드 된 파일이 없으면 null을 반환한다.
    getParameter(String name) : 요청 파라미터 이름이 name인 값을 전달받는다.
    getParameterNames() : 요청 파라미터 이름을 Enumeration 객체 타입으로 반환한다.
    getFile(String name) 서버에 업로드된 파일에 대한 파일 객체를 반환한다. 업로드된 파일이 없으면 null 반환
    getFilesystemName(String name) : 사용자가 설정하여 서버에 실제로 업로드된 파일명을 반환한다. 파일명이 중복되면 변경된 파일명이 반환됨
    getOriginalFileName(String name) : 사용자가 업로드한 실제 파일명을 반환한다. 파일명이 중복되면 변경 전의 파일명을 반환한다.

    Commonse-FileUpload를 이용한 파일 업로드

    파일 업로드 패키지인 Commons-FileUpload는 서버의 메모리 상에서, 파일 처리가 가능하도록 지원한다.

    이패 키지는 Commons-io 패키지를 바탕으로 작성되었기 때문에 웹 브라우저에서 서버로 파일을 업로드 하기 위해서는 commons-fileupload.jar, commons-io.jar 파일을 다운로드해서 사용해야한다. <%@ import="org.apache.commons.fileupload.* %>도 설정해주어야함.

     

     

     


    [웹 쇼핑몰] 상품 이미지 등록하기

    dto/Product.java - 이미지 등록을 위한 이미지 파일명 변수를 추가하고 게터 세터를 추가한다.

    private String filename; // 이미지 파일명
    public String getFilename() {
    		return filename;
    	}
    
    	public void setFilename(String filename) {
    		this.filename = filename;
    	}

    상품 데이터 접근 클래스 productRepository.java 수정 - setFilename으로 각자 이름 등록

    public ProductRepository() {
    		Product phone = new Product("P1234", "iPhone 6s", 800000);
    		phone.setDescription("4.7-inch, 1334X750 Renina HD display, 8-megapixel iSight Camera");
    		phone.setCategory("Smart Phone");
    		phone.setManufacturer("Apple");
    		phone.setUnitsInStock(1000);
    		phone.setCondition("New");
    		phone.setFilename("P1234.png");
    
    		Product notebook = new Product("P1235", "LG PC 그램", 1500000);
    		notebook.setDescription("13.3-inch, IPS LED display, 5rd Generation Intel Core processors");
    		notebook.setCategory("Notebook");
    		notebook.setManufacturer("LG");
    		notebook.setUnitsInStock(1000);
    		notebook.setCondition("Refurbished");
    		notebook.setFilename("P1235.png");
    
    		Product tablet = new Product("P1236", "Galaxy Tab S", 900000);
    		tablet.setDescription("212.8*125.6*6.6mm,  Super AMOLED display, Octa-Core processor");
    		tablet.setCategory("Tablet");
    		tablet.setManufacturer("Samsung");
    		tablet.setUnitsInStock(1000);
    		tablet.setCondition("Old");
    		tablet.setFilename("P1236.png");
    
    		listOfProducts.add(phone);
    		listOfProducts.add(notebook);
    		listOfProducts.add(tablet);
    	}

    product, products.jsp 수정 - getFIlename으로 파일명 추출하여 해당 src경로 폴더에 있는 이미지를 가져옴

    <div class="col-md-4">
    				<img src ="resources/images/<%=product.getFilename()%>" style ="width: 100%">
    				<h3><%=product.getPname()%></h3>
    				<p><%=product.getDescription()%>
    				<p><%=product.getUnitPrice()%>원
    				<p><a href="./product.jsp?id=<%=product.getProductId()%>" class="btn btn-secondary" role="button"> 상세 정보 &raquo;</a>
    			</div>
    <div class ="col-md-5">
    				<img src="resources/images/<%=product.getFilename()%>" style="width: 100%" />
    			</div>

    addProduct.jsp 수정

    <%@ page contentType="text/html; charset=utf-8"%>
    <html>
    <head>
    <link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" />
    <title>상품 등록</title>
    </head>
    <body>
    	<jsp:include page="menu.jsp" />	
    	<div class="jumbotron">
    		<div class="container">
    			<h1 class="display-3">상품 등록</h1>
    		</div>
    	</div>
    	<div class="container">
    		<form name="newProduct" action="./processAddProduct.jsp" class="form-horizontal" method="post" enctype ="multipart/form-data">
    			<div class="form-group row">
                
                //enctype 을 multipart/form-data로 바꿔주었음 -> 파일 업로드 규칙 2.
                //파일 업로드 규칙 1. method="post"
                //파일 업로드 규칙 3. action은 해당 동작 처리할 jsp로
                
                
    				<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="name" 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="unitPrice" class="form-control" >
    				</div>
    			</div>
    			<div class="form-group row">
    				<label class="col-sm-2">상세 정보</label>
    				<div class="col-sm-5">
    					<textarea name="description" cols="50" rows="2"
    						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" value="New " > 신규 제품 
    					<input type="radio" name="condition" value="Old" > 중고 제품 
    					<input type="radio" name="condition" value="Refurbished" > 재생 제품
    				</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>
                //이미지 파일을 받기 위한,, form 추가 하였음..
                //input type="file" 규칙 4!!
    			<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>
    </body>
    </html>

    processAddProduct.jsp 수정

    사용된 메소드는 위 게시물 참고하거나, 구글링,,

    <%@ page contentType="text/html; charset=utf-8"%>
    <%@ page import="com.oreilly.servlet.*"%>
    <%@ page import="com.oreilly.servlet.multipart.*"%>
    <%@ page import="java.util.*"%>
    <%@ page import="dto.Product"%>
    <%@ page import="dao.ProductRepository"%>
    
    <%
    	request.setCharacterEncoding("UTF-8");
    
    	String filename = "";
    	String realFolder = application.getRealPath("/"); //상대경로로 지정해준다.
    	String encType = "utf-8"; //인코딩 타입
    	int maxSize = 5 * 1024 * 1024; //최대 업로드될 파일의 크기5Mb
    
    	MultipartRequest multi = new MultipartRequest(request, realFolder+"resources/images", maxSize, encType, new DefaultFileRenamePolicy());
    	//MultipartRequest 클래스를 이용해 파일 업로드 하기 위해 먼저 MultipartRequest 객체 생성
    	String productId = multi.getParameter("productId");
    	
    	String name = multi.getParameter("name");
    	//getParameter - 요청 파라미터 이름이 name인값을 전달받음)
    	String unitPrice = multi.getParameter("unitPrice");
    	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");
    	
    	Integer price;
    
    	if (unitPrice.isEmpty())
    		price = 0;
    	else
    		price = Integer.valueOf(unitPrice);
    
    	long stock;
    
    	if (unitsInStock.isEmpty())
    		stock = 0;
    	else
    		stock = Long.valueOf(unitsInStock);
    
    	
    	Enumeration files = multi.getFileNames();
    	String fname = (String) files.nextElement();
    	String fileName = multi.getFilesystemName(fname);
    	//multi 메소드를 사용하여 웹 브라우저가 전송한 multipart/form-data 유형 요청 파라미터를 읽어오고 파일을 업로드
    	
    	
    	ProductRepository dao = ProductRepository.getInstance();
    
    	Product newProduct = new Product();
    	newProduct.setProductId(productId);
    	newProduct.setPname(name);
    	newProduct.setUnitPrice(price);
    	newProduct.setDescription(description);
    	newProduct.setManufacturer(manufacturer);
    	newProduct.setCategory(category);
    	newProduct.setUnitsInStock(stock);
    	newProduct.setCondition(condition);
    	newProduct.setFilename(fileName);
    
    	dao.addProduct(newProduct);
    
    	response.sendRedirect("products.jsp");
    %>

    'jsp' 카테고리의 다른 글

    HTTP,쿠키,세션  (1) 2023.05.30
    [jsp] 쿠키생성, 쿠키 정보 얻기, 쿠키 삭제  (0) 2023.05.24
    [jsp] 유효성 검사  (3) 2023.04.25
    [jsp] 폼 태그  (0) 2023.04.25
    [jsp] 스크립트 태그  (0) 2023.03.19

    댓글

lee-ding