본문 바로가기

JSP, Servlet, MySQL/JSP - webmarket

파일 업로드 : 상품 이미지 등록하기 2 /파일업로드 상태 500 내부 서버 오류/Not a directory

728x90
반응형

03. Commons-FileUpload 를 이용한 파일 업로드

파일 업로드 패키지인 Commons-FileUpload 는 서버의 메모리상에서 파일 처리가 가능하도록 지원한다. 이 패키지는 Commons-io 패키지를 바탕으로 작성되었기 때문에 웹 브라우저에서 서버로 파일을 업로드하기 위해 오픈 라이브러리 commons-fileupload.jar.commons-io.jar 파일을 다음 배포 사이트에서 직접 다운로드 해서 사요ㅗㅇ한다. 그리고 jsp 페이지에 page 디렉티브 태그의 import 속성을 사용하여 패키지 org.apache.commons.fileupload.*  를 설정해야 한다. 

  • 배포 사이트 : http://commons.apache.org/downloads/
  • 다운로드 파일:commons-fileupload-1.3.3-bin.zip,commons-io-2.6-bin.zi

 

아래 링크 누루면 파일 다운로드 페이지로 바로 간다. 잘 찾아보면 보인다. 

https://archive.apache.org/dist/commons/io/binaries/

 

Index of /dist/commons/io/binaries

 

archive.apache.org

NOTE_ 오픈 라이브러리 Commons-FileUpload.jar, commons-io.jar 설치 방법

  1. 배포 사이트에서 commons-fileupload-1.3.3-bin.zip 와 commons-io-2.6-bin.zip 파일을 다운로드 한다. 
  2. 다운로드한 두 파일의 압축을 푼다.
  3. 압축을 푼 두 파일의 commons-fileupload-1.3.3-bin,commons-io-2.6-bin 폴더에 있는 commons-fileupload-1.3.2.jar,commons-io-2.6.kar 파일을 찾는다.
  4. 웹 애플리케이션의 /WebContent/WEB-INF/lib 폴더에 commons-fileupload-1.3.2.jar, commons-io-2.6.kar 파일을 포함한다. 또는 서버 톰캣의 /common/lib 폴더와 자바 JDK lib 폴더에 commons-fileupload-1.3.2.jar,commons-io-2.6.kar 파일을 포함한다. 
<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="com.oreilly.servlet.*" %>
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>

<html>
<head>
<title>File Upload</title>
</head>
<body>


	
	<%
		String fileUploadPath = "C:\\upload";
        
        //Commons-FileUpload 를 이용하여 파일을 업로드 하려면 먼저
        //Commons-FileUpload 패키지에 포함되어있는 DiskFileUpload 객체를 생성한다
        DiskFileUpload upload = new DiskFileUpload();
        
        //생성된 객체를 통해 DiskFileUpload 클래스가 제공하는 메소드를 사용하여 
        //웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 가져온다. 
        List items = upload.parseRequest(request);
        
        Iterator params = items.iterator();
        
        while(params.hasNext()){
        	
            //FileItem클래스의 메소드를 사용하여 요청 파라미터가 일반 데이터인지
            //파일인지 분석 및 처리하여 파일을 업로드 한다. 
            FileItem item = (FileItem)params.next();
            if(item.isFormField()){
                String title = item.getString("UTF-8");
                out.println("<h3>" + title + "</h3>");
            }else{
                String fileName = item.getName();
                fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
                File file = new File(fileUploadPath + "/" + fileName);
                item.write(file);
                out.println("파일 이름 : " + fileName+ "<br>");
            }
      	}
	%>
	
</body>
</html>

 

DiskFileUpload 클래스의 메소드

메소드 유형 설명
setRepositoryPath(String repositoryPath) void 업로드된 파일을 임시로 저장할 디렉터리를 설정한다.
setSizeMax(long sizeMax) void  최대파일의 크기를 설정한다
setSizeThreshold(int sizeThreshold) void 메모리상에 저장할 최대 크기를 설정한다
parseRequest(HttpServietRequest req) List<FileItem> multipart/form-data 유형의 요청 파라미터를 가져온다

 

FileItem 클래스의 메소드

메소드 유형 설명
isFormFeld() boolean 요청 파라미터가 파일이 아니라 인반 데이터인 경우 true를 반환한다
getFieldName() String 요청 파라미터의 이름을 얻어온다
getString() String  기본 문자 인코딩을 사용하여 요청 파라미터의 값을 얻어온다
getString(String encoding) String 설정한 문자 인코딩을 사용하여 요청 파라미터의 값을 얻어온다
getName() String 업로드된 파일(경로포함)의 이름을 얻어온다
getSize() long 업로드된 파일의 크기를 얻어온다
get() byte[] 업로드된 파일을 바이트 배열로 얻어온다
insInMermory() boolean 업로드된 파일이 메모리에 저장된 상태인 경우 true를 반환하고 임시 디렉터리에 저장된 경우 false를 반환한다
delete() void 파일과 관련된 자원을 삭제한다. 메모리상에 저장된 경우 할당된 메모리를 반환하고, 임시파일로 저장된 경우 파일을 삭제한다
write() void 파일과 관련된 자원을 저장한다
getContentType() String 웹 브라우저가 전송하는 콘텐츠 유형을 반환하고, 정의되어 있지 않은 경우 null을 반환한다

 

NOTE_ FIleItem 클래스로 업로드 파일을 저장하는 방법

  1. write()메소드를 사용한다
  2. getInputStream()메소드로 입력 스트림으로부터 바이트 데이터를 가져와 FileOutputStream()을 사용하여 파일에 출력한다.
  3. get()메소드로 가져온 바이트 배열을 FileOutputStram을 사용하여 파일에 출력한다. 

Srite()메소드는 주로 로컬 디스크에 직접 업로드한 파일을 저장할 때 사용하고, getInputStram()이나 get()메소드는 업로드한 파일에 특별한 처리를 하거나 데이터베이스와 같이 디스크가 아닌 영역에 업로드한 파일을 저장할 때 사용한다.

*FileItem클래스의 메소드 참고 사이트 : https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html 

 

FileItem (Apache Commons FileUpload 1.5 API)

A convenience method to write an uploaded item to disk. The client code is not concerned with whether or not the item is stored in memory, or on disk in a temporary location. They just want to write the uploaded item to a file. This method is not guarantee

commons.apache.org

 

 

=Commons-FileUpload 를 이용하여 파일 업로드 하기=

 

 

/ch07/fileupload03.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>File Upload</title>
</head>
<body>

    <!-- 파일 업로드를 위해 폼 태그에 속성 값을 작성 -->
	<form action="fileupload03_process.jsp" method="post" enctype="multipart/form-data">
		<p>파일 : <input type="file" name="filename">
		<p> <input type="submit" value="파일 올리기">
	</form>
</body>
</html>

/ch07/fileupload03_process.jsp

<%@ page contentType="text/html; charset=utf-8" %>

<!-- commons-FileUpload 패키지를 사용하기위해 import해줌 -->
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>

<html>
<head>
<title>File Upload</title>
</head>
<body>
	<%
		//폼페이지에서 전송된 파일을 저장할 서버의 경로를 작성해줌.
		String fileUploadPath = "C:\\upload";
	
		//파일 업로드를 위해 DistFileUpload 클래스를 생성
		DiskFileUpload upload = new DiskFileUpload();
		
		//폼페이지에서 전송된 요청 파라미터를 전달받도록 DistFileupload 객체 타입의 parseRequest()메소드를 작성.
		List items = upload.parseRequest(request);
		
		//폼페이지에서 전송된 요청 파라미터를 Iterator 클래스로 변환
		Iterator params = items.iterator();
		
		//폼페이제서 전송된 요청 파라미터가 없을 때까지 반복하도록 Iterator 객체 타입의 hasNext()메소드를 작성
		while(params.hasNext()){
			//폼페이지에서 전송된 요청 파라미터의 이름을 가져오도록 Iterator 객체 타입의 next()메소드를 작성
			FileItem fileItem = (FileItem)params.next();
			
			//폼페이지에서 전송된 요청 파라미터가 파일이면 서버의 파일 저장 경로에 업로드 파일을 저장하도록 작성. 
			if(!fileItem.isFormField()){
				String fileName = fileItem.getName();
				fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
				File file = new File(fileUploadPath + "/" + fileName);
				fileItem.write(file);
			}
		}
		
	%>
</body>
</html>

업로드할 파일을 선택
로컬디스크(C:) 에 있는 upload 디렉터리에 '3'파일이 업로드된 상태

 

 

=Commons-FileUpload를 이용하여 파일 업로드 및 정보 출력하기=

/ch07/fileupload04.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>File Upload</title>
</head>
<body>n

    <!-- 파일 업로드를 위해 폼 태그에 속성 값을 작성 -->
	<form action="fileupload03_process.jsp" method="post" enctype="multipart/form-data">
		<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>

/ch07/fileupload04_process.jsp

 

<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>

<html>
<head>
<title>File Upload</title>
</head>
<body>
	<%
		String path = "C:\\upload";
	
		//파일 업로드를 위해 DistFileUpload 클래스를 생성
		DiskFileUpload upload = new DiskFileUpload();
		
		
		//업로드할 파일의 초대 크기, 메모리상에 저장할 최대 크기, 업로드된 파일을 임시로 저장할 경로를 작성
		upload.setSizeMax(1000000);
		upload.setSizeThreshold(4096);
		upload.setRepositoryPath(path);
		
		//폼페이지에서 전송된 요청 파라미터를 전달받도록 DistFileupload 객체 타입의 parseRequest()메소드를 작성.
		List items = upload.parseRequest(request);
		
		//폼페이지에서 전송된 요청 파라미터를 Iterator 클래스로 변환
		Iterator params = items.iterator();
		
		//폼페이제서 전송된 요청 파라미터가 없을 때까지 반복하도록 Iterator 객체 타입의 hasNext()메소드를 작성
		while(params.hasNext()){
			//폼페이지에서 전송된 요청 파라미터의 이름을 가져오도록 Iterator 객체 타입의 next()메소드를 작성
			FileItem item = (FileItem)params.next();
			
			//폼페이지에서 정송된 요청 파라미터가 일반 데이터면 요청 파라미터의 이름과 값을 출력하도록 out 내장객체의 println()메소드를 작성
			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();
				
				fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
				long fileSize = item.getSize();
				
				File file = new File(path + "/" + fileName);
				item.write(file);
				
				out.println("__________________<br>");
				out.println("요청 파라미터 이름 : " +fileFieldName + "<br>");
				out.println("저장 파일 이름 :"+ fileName+"<br>");
				out.println("파일 콘텐츠 유형 : " +contentType+"<br>");
				out.println("파일 크기 : " + fileSize);
			}
		}
		
	%>
</body>
</html>

 

 

04. 쇼핑몰 - 상품 이미지 등록하기

 

파일 업로드 처리방법을 이용하여 상품 이미지를 등록할 수 있는 폼페이지를 만들고 상품 이미지를 업로드하여 상품 이미지를 출력한다. 

 

=정적 리소스(상품 이미지 및 부트스트랩 CSS)관리하기=

 

1.상품 클래스에 멤버 변수 추가하기 : 상품 이미지를 저장 및 관리하기 위해 Product 클래스에 다음과 같이 필드를 선언한다. 

 

2.추가된 멤버 변수의 Setter/Getter() 메소드 작성하기 : 추가된 멤버 변수 filename 의 Setter/Getter()메소드를 각각 추가한다. 

package dto;

import java.io.Serializable;

public class Product implements Serializable {
	
	
	//멤버 변수 filename의 Setter/Getter()메소드 추가
	public String getFilename() {
		return filename;
	}
	
	public void setFilename(String filename) {
		this.filename = filename;
	}

	private static final long serialVersionUID = -4274700572038677000L;
	
	private String productId; //상품 아이디
	private String pname; //상품명
	private Integer unitPrice; //상품가격
	private String description; //상품 설명
	private String manufacturer; // 제조사
	private String category; //분류
	private long unitsInStock; //제고 수
	private String condition; //신상품 or 중고품 or 재생품
	private String filename;   //이미지 파일명
	
	public Product() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Product(String productId, String pname, Integer unitPrice) {
	
		this.productId = productId;
		this.pname = pname;
		this.unitPrice = unitPrice;
		
		
	}

	public String getProductId() {
		return productId;
	}

	public void setProductId(String productId) {
		this.productId = productId;
	}

	public String getPname() {
		return pname;
	}

	public void setPname(String pname) {
		this.pname = pname;
	}

	public Integer getUnitPrice() {
		return unitPrice;
	}

	public void setUnitPrice(Integer unitPrice) {
		this.unitPrice = unitPrice;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getManufacturer() {
		return manufacturer;
	}

	public void setManufacturer(String manufacturer) {
		this.manufacturer = manufacturer;
	}

	public String getCategory() {
		return category;
	}

	public void setCategory(String category) {
		this.category = category;
	}

	public long getUnitsInStock() {
		return unitsInStock;
	}

	public void setUnitsInStock(long unitsInStock) {
		this.unitsInStock = unitsInStock;
	}

	public String getCondition() {
		return condition;
	}

	public void setCondition(String condition) {
		this.condition = condition;
	}
	
	
}

 

3. 상품 데이터 접근 클래스 수정하기 : ProductRepository 클래스의 기본 생성자에 상품 이미지를 설정하도록 다음과 같이 추가작성한다. 

package dao;

import java.util.ArrayList;

import dto.Product;
public class ProductRepository {
	
	private ArrayList<Product> listOfProducts = new ArrayList<Product>();
	private static ProductRepository instance = new ProductRepository(); //ProductRepository 클래스의 기본 생성자에 대한 객체 변수 instance를 작성한다. 
	
	public static ProductRepository getInstance() { //객체 변수 instance 에 대한 Getter()메소드를 작성한다. 
		return instance;
	}
	
	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 그램",150000);
		notebook.setDescription("13.3-inch, IPS LED display , 5rd Generation Intel Core processors");
		notebook.setCategory("Notebook");
		notebook.setManufacturer("LG");
		notebook.setUnitsInStock(1000);
		notebook.setCondition("Refurbishe");
		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);
		
		
	}
	
	public ArrayList<Product>getAllProducts(){
		return listOfProducts;
	}
	
	//상품 상세 정보 표시하기 chapter05
	public Product getProductById(String productId) { 
		Product productById = null;
		
		for(int i=0; i<listOfProducts.size(); i++) {
			
			Product product = listOfProducts.get(i);
			if(product != null && product.getProductId() != null && product.getProductId().equals(productId)){
				
					productById = product;
					break;
			}
		} //객체 변수 listOfProducts 에 저장된 모든 상품 목록에서 상품 아이디와 일치하는 상품을 가져오는 getProductById()메소드를 작성
		return productById;
	}
	
	public void addProduct(Product product) { //객체변수 listOfProducts 에 새로운 상품 정보를 등록하는 addProduct()메소드를 작성 한다. 
		listOfProducts.add(product);
	}
}

4. 정적 리소스 관리 폴더 만들기: /WebContent/폴더에 resources 폴더를 생성하고, 여기에 이미지파일을 관리하는 images 폴더와 부트스트랩 파일( bootstrap.min.css)을 관리하는 css폴더를 생성한다. 

  • 생성된 image 폴더에 이미지 파일명을 상품 아이디로 하여 등록한다.
  • css폴더에 부트스트램 css 파일(bootstrap.min.css)을 다운로드 하여 등록한다. 

5.상품 목록 페이지 수정하기 : products.jsp 파일에 부트스트랩 css를 포함하고 상품 이미지를 출력하기 위해 다음과 같이 수정한다.  (이미지 태그에 alt 는 웹접근성을 위하여 꼭 입력하였으면 하는 바램이다 ㅜㅜ, 책에는 나와있지 않음..)

 

<%@ page contentType="text/html; charset=utf-8"%>
<%@ page import="java.util.ArrayList"%>
<%@ page import="dto.Product" %>
<%@ page import="dao.ProductRepository" %>
<jsp:useBean id="productDAO" class="dao.ProductRepository" scope="session" />
<html>
	<head>
		<link rel="stylesheet" href="./resources/css/bootstrap.mis.css">
		<title>상품목록</title>
	</head>
	<body>
		<jsp:include page="menu.jsp"/>
		<div class="jumbotron">
			<div class="container">
				<h1 class="display-3">상품 목록</h1>
			</div>
		</div>
		<%
			//ProductRepository 클래스의 객체변수 instance를 호출하는 getInstance()메소드를 작성한다.
			//이를통해 getAllProducts()메소드를 호출하여 반환 결과 값을 ArrayList<Product>객체타입의 변수 listOfProducts에 저장한다. 
			ProductRepository dao = ProductRepository.getInstance();
			ArrayList<Product> listOfProducts = dao.getAllProducts();
			//ArrayList<Product> listOfProducts = productDAO.getAllProducts();
		%>
		<div class="container">
			<div class="row" align="center">
				<%
					for(int i = 0; i<listOfProducts.size();i++){
						Product product = listOfProducts.get(i);
					
				%>
				<div class="col-md-4">
					<img alt="상품이미지" src="./resources/images/<%=product.getFilename()%>" style="width:100%"> <!-- html 태그에 바로 style 준거 너무 거슬리긴 한데 jsp 공부중이니 넘어가도록 하자..-->
					<h3><%= product.getPname() %></h3>
					<p><%= product.getDescription() %></p>
					<p><%= product.getUnitPrice() %>원</p>
					<p><a href="./product.jsp?id=<%=product.getProductId() %>"class = "btn btn-secondary" role="button"> 상세 정보 &raquo;</a>  
					<!-- 상품 아이디에 대한 상세 정보 페이지가 연결되도록 <상세정보>버튼을 작성 -->
				</div>
				<%
					}
				%>
			</div>
			<hr>
		</div>
		<jsp:include page="footer.jsp"/>
	</body>
</html>

6. 상품 상세 정보 페이지 수정하기 : product.jsp 파일에 부트스랩 css 를 포함하고 상품 이미지를 출력하기 위해 다음과 같이 수정한 후 웹 브라우저에서 확인해보자 

<%@ page contentType="text/html; charset=utf-8"%>
<!--  생성한 상품 클래스 dto.Product 패키기를 사용하기 위해 page 디렉티브 태그 import -->
<%@ page import="dto.Product" %> 
<!-- 기존에 작성된 useBean액션태그를 없애고 상품접근 클래스 dao.ProductRepository 패키지를 사용하기위해 page디렉티브 태그의 import속성을 작성 -->
<%@ page import="dao.ProductRepository" %>

<!-- 자바빈즈로 생성한 ProductRepository 클래스를 사용하도록 useBean 액션 태그를 작성한다 -->
<!--  jsp:useBean id="productDAO" class="dao.ProductRepository" scope="session" /-->


<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>
		<%
			String id = request.getParameter("id"); //상품 목록 페이지로부터 전달되는 상품 아이디를 전송받도록 request내장 객체의 getParameter()메소드를 작성
			
			//ProductRepository클래스의 객체 변수 instance를 호출하는 getInstance()메소드를 작성한다. 
			//이를통해getProductById()메소드를 호출하여 반환 결과 값을 Product 객체 타입의 변수 product에 저장한다. 
			ProductRepository dao = ProductRepository.getInstance();
			Product product = dao.getProductById(id);
			
			
			//useBean를 사용했을시에 예제
			//Product product = productDAO.getProductById(id);
			//useBean 액션 태그에 id 속성 값을 통해 ProductRepository클래스의 
			//getProductById()메소드를 호출하여 반환된 결과 값을 Product 객체 타입의 변수 Product 에 저장하도록 작성한다.  
			
		%>                                                 
		<div class="container">
			<div class="row">
			
				<div class="col-md-5">
					<img alt="상품이미지" src="./resources/images/<%=product.getFilename()%>" style="width:100%">
				</div>
				<div class="col=md-6"> <!-- Product 객체 타입의 변수 product 에 저장된 상품명, 상품 상세 정보, 상품 코드, 제조사, 분류, 재고 수 , 상품 가격 등을 
				출력하도록 표현문 태그를 작성 -->
						<h3><%=product.getPname() %></h3>
						<p><%=product.getDescription()%>
						<p> <b>상품 코드 : </b><span class="badge badge-danger">
							<%=product.getProductId() %></span>
						<p> <b>제조사</b> :<%=product.getManufacturer() %>
						<p> <b>분류</b> :<%=product.getCategory() %>
						<p>	<b>재고 수</b> : <%=product.getUnitsInStock() %>
						<h4><%=product.getUnitPrice() %></h4>
						<!-- <상품주문>,<상품 목록> 버튼을 작성한다 -->
						<p> <a href="#" class="btn btn-info">상품 주문 &raquo;</a>
						<a href="./products.jsp" class="btn btn-secondary"> 상품 목록 &raquo;</a>
									
				</div>
			</div>
		</div>
		<jsp:include page="footer.jsp"/>
	</body>
</html>

상품 목록 페이지 (Products.jsp)
상품 정보 페이지 (products.jsp)

 

 

- 상품 이미지 업로드 하기

1. 상품 이미지 파일의 저장 위치 만들기 : C드라이브에 upload 폴더를 생성하고 이 폴더에 상품 이미지파일명을 상품 아이디로 하여 등록한다. 

2. 오픈 라이브러리 cos.jar 등록하기 : MultipartRequest 클래스를 이용한 파일 업로드를 위해 /WebContent/WEB-INF/lib 폴더에 cos.jar 파일을 등록한다. 

 

3. 상품 목록 페이지 수정하기 : C:\upload 폴더에 저장된 상품 이미지를 출력하기 위해 다음과 같이 products.jsp 파일을 수정

<div class="col-md-4">
					<img alt="상품이미지" src="c:/upload/<%=product.getFilename()%>" style="width:100%">
					<h3><%= product.getPname() %></h3>
					<p><%= product.getDescription() %></p>
					<p><%= product.getUnitPrice() %>원</p>
					<p><a href="./product.jsp?id=<%=product.getProductId() %>"class = "btn btn-secondary" role="button"> 상세 정보 &raquo;</a>  
					<!-- 상품 아이디에 대한 상세 정보 페이지가 연결되도록 <상세정보>버튼을 작성 -->
				</div>

4.상품 상세 정보 페이지 수정하기: C:\upload 폴더에 저장된 상품 이미지를 출력하기 위해 다음과 같이 product.jsp 파일을 수정한다 

<div class="row">
			
				<div class="col-md-5">
					<img alt="상품이미지" src="c:/upload/<%=product.getFilename()%>" style="width:100%">
				</div>
				<div class="col=md-6"> <!-- Product 객체 타입의 변수 product 에 저장된 상품명, 상품 상세 정보, 상품 코드, 제조사, 분류, 재고 수 , 상품 가격 등을 
				출력하도록 표현문 태그를 작성 -->
						<h3><%=product.getPname() %></h3>
						<p><%=product.getDescription()%>
						<p> <b>상품 코드 : </b><span class="badge badge-danger">
							<%=product.getProductId() %></span>
						<p> <b>제조사</b> :<%=product.getManufacturer() %>
						<p> <b>분류</b> :<%=product.getCategory() %>
						<p>	<b>재고 수</b> : <%=product.getUnitsInStock() %>
						<h4><%=product.getUnitPrice() %></h4>
						<!-- <상품주문>,<상품 목록> 버튼을 작성한다 -->
						<p> <a href="#" class="btn btn-info">상품 주문 &raquo;</a>
						<a href="./products.jsp" class="btn btn-secondary"> 상품 목록 &raquo;</a>
									
				</div>
			</div>

5. 상품 정보 등록 페이지 수정하기: addProduct.jsp 파일에 부트스트랩 css를 포함하고 상품 이미지를 업로드 하기 위해 다음과 같이 수정. 

<%@ 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">
		<!-- 파일업로드를 위한 폼 태그에 enctype 속성값을 추가로 작성해준다.  -->
		<form name="newProduct" action="./processAddProduct.jsp" class="form-horizontal" method="post" 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="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-3">
					<textarea name="description" cols="50" rows="2" class="form-control"></textarea><!-- 상품 설명값을 여러줄로 입력받도록 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="unitInStock" class="form-control">
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상태</label> <!-- 상품 상태값중 하나만 선택 입력받도록 radio로 작성 -->
				<div class="col-sm-5">
					<input type="radio" name="condition" value="New"> 신규 제품    
					<input type="radio" name="condition" value="Ole"> 중고 제품           
					<input type="radio" name="condition" value="Refurbished"> 재생 제품                     
				</div>
			</div>
			
			<!-- 파일을 입력받도록 input 태그의 type 속성값을 file로 작성, name 속성을 작성한다.  -->
			<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">
				<div class="col-sm-offset-2 col-sm-10">
					<input type="submit" class="btn btn-primary" value="등록"> <!-- 입력된 데이터를 서버로 전송하도록 input 태그의 type 속성값을 submit로 작성 -->
				</div>
			</div>
		</form>
	</div>
</body>
</html>

6. 상품 등록 처리 페이지 수정하기 : 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 = "C:\\upload"; //웹 애플리케이션상의 절대 경로
	int maxSize = 5 * 1024 * 1024; //최대 업로드될 파일의 크기 5MB
	String encType = "utf-8"; //인코딩 유형
	
	//MultipartRequest 객체를 생성하도록 MultipartRequest 생성자를 작성한다. 매개변수로 바로 위행에 설정된 값과 DefaultFileRenamePolicy 클래스를 설정한다. 
	MultipartRequest multi = new MultipartRequest(request, realFolder, maxSize, encType, new DefaultFileRenamePolicy());

	//폼 페이지에서 입력된 요청 파라미터 값을 얻어오도록 요청 파라미터의 이름을 설정하여 MultipartRequest 객체타입의 getParameter()메소드를 작성한다. 
	String productId = multi.getParameter("productId");
	String name = multi.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("unitInStock");
	String condition = multi.getParameter("condition");
	
	//폼 페이지에서 상품 가격이 입력 되지 않은 경우 0 으로, 입력된 경우 정수형으로 변경하도록 작성한다. 
	Integer price;
	
	if(unitPrice.isEmpty())
		price = 0;
	else
		price = Integer.valueOf(unitPrice);
	
	//폼 페이지에서 상품 재고 수가 입력되지 않은 경우 0 으로, 입력된 경우 정수형으로 변경하도록 작성한다. 
	long stock = 0;
	
	if(unitsInStock.isEmpty())
		stock = 0;
	else
		stock = Long.valueOf(unitsInStock);
	
	//폼 페이지에서 전송된 요청 파라미터 중 파일을 받도록 MultipartRequest 객체타입의 getFileNames()메소드를 작성
	Enumeration files = multi.getFileNames();
	//폼 페이지에서 전송된 요청파라미터 중 파일을 받도록 Enumeration 객체 타입의 nextElement()메소드를 작성.
	String fname = (String)files.nextElement();
	//폼페이지에서 전송되어 서버에 업로드된 파일을 가져오도록 MultipartRequest 객체 타입의 getFilesystemName()메소드를작성. 
	String fileName = multi.getFilesystemName(fname);
	
	
	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); //폼 페이지에서 입력된 데이터를 저장하도록 ProductRepository 클래스의 addProduct()메소드를 호출한다. 
	
	response.sendRedirect("products.jsp"); //products.jsp ㅍ이지로 강제 이동하도록 response 내장 객체의 sendRedirect()메소드를 작성.
	
%>

 

 

요약

01. 파일 업로드의 개요

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

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

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

03. Commons-FileUpload를 이용한 파일 업로드

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

 

728x90
반응형