contents
PART 03 페이지 처리 기법
chapter 07 파일 업로드: 도서 이미지 등록하기
01.파일 업로드의 개요
02.MultipartRequest를 이용한 파일 업로드
03.Commons-FileUPload를 이용한 파일 업로드
04.북마켓 도서 이미지 등록하기
------------------------------------------------
PART 03 페이지 처리 기법
chapter 07 파일 업로드: 도서 이미지 등록하기
01.파일 업로드의 개요
-파일 업로드(file upload)는 웹 브라우저에서 서버로 파일을 전송하여 서버에 저장하는 것을 말함. 서버로 업로드할 수 있는 파일에는 텍스츠 파일, 바이너리 파일, 이미지 파일, 문서 등 다양한 유형이 있음. 웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 사용하고, 전송된 파일을 서버에 저장하기 위해 오픈 라이브러리를 이용해야 함
*문자열: 1.text 2.바이너리(010101)->숫자(2진수): 이미지 x n=> 영상
실행파일: .exe
.class
1)파일 업로드를 위한 JSP 페이지
-웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 작성할 때 몇 가지 중요한 규칙을 따라야 하며 그 형식은 다음과 같음
| <form action="JSP 파일" method="POST" enctype="multipart/form-date"> <input type="file" name="요청 파라미터 이름"> </form> |
(1)form 태그의 method 속성은 반드시 POST 방식으로 설정해야 함
(2)form 태그의 enctype 속성은 반드시 multipart/form-data로 설정해야 함
(3)form 태그의 action 속성은 파일 업로드를 처리할 JSP 파일로 설정해야 함
(4)파일 업로드를 위해 input 태그의 type 속성을 file로 설정해야 함. 만약 여러 파일을 업로드하려면 2개 이상의 input 태그를 사용하고 name 속성에 서로 다른 값을 설정함
2)파일 업로드 처리 방법
-웹 브라우저에서 서버로 파일을 업로드하면 서버는 요청 파라미터를 분석하여 파일을 찾고 서버의 자원(파일 저장 폴더)에 저장하는 과정을 거침. 이러한 파일 업로드의 처리는 단순한 자바 코드로 작성하여 처리할 수 없어 다음과 같이 오픈 라이브러리인 cos.jar 또는 commonsfileupload.jar를 사용해야 함
◎파일 업로드 처리 방법
| 종류 | 특징 | 필요한 라이브러리 |
| MultipartRequest 이용하기 | 가장 간단한 방법 | cos.jar |
| 아파치 API 이용하기 | 편리하고 강력한 API 제공 | commons-fileupload.jar commons-io.jar |
*text+숫자 섞여있는 거 가져올 수 있는 방법: 둘 중 하나 써야함
◎JavaEE에서 JakartaEE로 마이그레이션하는 방법
-마이그레이션이란 데이터나 소프트웨어를 현행 시스템 환경에서 새로운 환경으로 시스템을 전환하는 것을 의미함. 그래서 톰캣 10전번을 사용할 경우 기존에 톰캣 9번전 이하에서 사용하던 라이브러리를 새로운 환경 시스템에 맞게 다음과 같이 마이그레이션해야 함
-톰캣 9와 톰캣 10은 API 구현체가 완전히 달라짐. 톰캣 9까지는 JavaEE가 적용되고, 톰캣 10부터는 JakartaEE가 적용됨. 서블릿 5.0은 JakartaEE부터 지원되므로, 해당 버전의 시블릿을 JavaEE로 구동하거나, 더 낮은 버전의 서블릿을 JakartaEE로 구동하면 서블릿이 정상적으로 동작하지 않아 404 오류가 발생함
| JavaEE | JakartaEE | |
| 서블릿(Servlet) | javax.servlet | Jakarta.servlet |
| 톰캣 버전 | 10.0버전 | 10.0 이후부터 |
-JavaEE와 JakartaEE는 자바 코드의 내부 로직이나 구조적으로 많은 것이 변경되었음. 대표적으로 직접 확인 할 수 있는 것은 패키지의 변경임. 따라서 Javax.*을 Jakarta.*로 변경하는 것만으로도 마이그레이션이 가능함
02.MultipartRequest를 이용한 파일 업로드
-MultipartRequest는 웹 페이지에서 서버로 업로드되는 파일 자체만 다루는 클래스임. 웹 브라우저가 전송한 Multipart/form-data 유형과 POST 방식의 요청 파라미터 등을 분석한 후 일반 데이터와 파일 데이터를 구분하여 파일 데이터에 접근함. 또한 한글 인코딩 값을 얻기 쉽고, 서버의 파일 저장 폴더에 동일한 파일명이 있으면 파일명을 자동으로 변경함
-MultipartRequest 클래스는 cos(com.oreilly.servlet) 패키지에 포함되어 있는 파일 업로드 컴포넌트로, 오픈 라이브러리 cos.jar를 다음 배포 사이트에서 직접 다운로드해서 사용함. 그리고 JSP 페이지에 page 디렉티브 태그의 import 속성을 사용하려 패키지 com.oreilly.servlet.*을 설정해야 함
*라이브러리에 직접 넣어야 함(자동x)
·배포 사이트: http://www.servlets.com/cos
·다운로드 파일: cos-22.05.zip
·설치방법: 압축 푼 파일의 lib 폴더에 있는 cos.jar 찾기 -> /src/main/webapp/WEB-INF/lib/ 폴더에 cos.jar 파일 포함
Servlets.com | com.oreilly.servlet
www.servlets.com
-MultipartRequest 클래스를 이용하여 파일을 업로드하려면 먼저 MultipartRequest 객체를 생성함. 그리고 생성된 객체를 통해 MultipartRequest 클래스가 제공하는 메소드를 사용하여 웹 브라우저가 전송한 Multipart/form-data 유형의 요청 파라미터를 읽어오고 파일을 업로드함
1)MultipartRequest 클래스 생성
-MultipartRequest 클래스는 다양한 생성자를 제공함. 그중에서 한글 인코딩 값을 쉽게 얻을 수 있고, 업로드되는 파일이 서버에 저장된 기존 파일과 중복될 때 자동으로 변경해주는 생성자의 형식은 다음과 같음
| MultipartRequest(javax.servlet.http.HttpServletRequest request, java.lang.String saveDirectory, int maxPostSize, java.lang.String encoding, FileRenamePolicy policy) |
◎MultipartRequest 생성자의 매개변수
| 매개변수 | 설명 |
| request | Request 내장 객체를 설정함 |
| saveDirectoty | 서버의 파일 저장 경로를 설정함 |
| maxPostSize | 파일의 최대 크기(바이트 단위)를 설정함. 최대 크기를 초과하면 IOException이 발생함 |
| encoding | 인코딩 유형을 설정함 |
| policy | 파일명 변경 정책을 설정함. saveDirectory에 파일명이 중복되는 경우 덮어쓰기 여부를 설정하며, 설정하지 않으면 덮어씀 |
-다음은 MultipartRequest 클래스를 생성하는 예임. 웹 브라우저에서 전송되는 파일을 서버의 C:\upload\ 경로에 저장하며, 파일의 최대 크기는 5MB(5 X 1,024 X 1,024B)이고, 파일명의 인코딩 유형은 utf-8로 설정함. 또한 서버에 저장된 파일명 중복을 처리하기 위해 DefaultFileRenamePolicy 클래스를 사용함. 즉 DefaultFileRenamePolicy 클래스는 서버에 동일한 파일이 존재하면 웹 브라우저에서 전송된 파일명 뒤에 숫자를 덧붙여 파일명이 중복되지 않게 함. DefaultFileRenamePolicy 클래스를 사용하려면 JSP 페이지에 page 디렉티브 태그의 import 속성으로 패키지 com.oreilly.servlet.multipart.*를 설정해야 함
[MultipartRequest 클래스 생성 예]
| <% page import="com.oreillyservlet.*" %> <% page import="com.oreillyservlet.multipart*" %> ··· (생략) ··· MultipartRequest multi=new MultipartRequest(request, "C:\\upload", 5*1024*1024, "utf-8", new DefaultFileRenamePolicy()) |
cf)5*1024kb*1024kb = 5MB
2)MultipartRequest 메소드
-웹 브라우저에서 전송한 multipart/form-data 유형의 요청 파라미터를 쉽게 읽어오고 파일을 업로드할 수 있도록 MultipartRequest 클래스에는 다양한 메소드가 있음. 웹 브라우저에서 전송되는 요청 파라미터 중 일반 데이터는 getParameter() 메소드로 값을 받을 수 있지만 파일의 경우 getFileNames() 메소드를 이용하여 데이터를 받음
◎MultipartRequest 메소드의 종류
| 메소드 | 유형 | 설명 |
| getContentType(String name) | String | 업로드된 파일의 콘텐츠 유형을 반환함. 업로드된 파일이 없으면 null을 반환함 |
| getParameter(String name) | String | 요청 피라미터 이름이 name인 값을 전달받음 |
| getParameterNames() | java.util.Enumeration | 요청 피라미터 이름을 Enumeration 객체 타입으로 반환함 |
| getFile(String name) | java.io.File | 서버에 업로드된 파일에 대한 파일 객체를 반환함. 업로드된 파일이 없으면 null을 반환함 |
| getFileNames() | java.util.Enumeration | 폼 페이지에 input 태그 내 type 속성 값이 file로 설정된 요청 파라미터의 이름을 반환함 |
| getFilesystemName(String name) |
String | 사용자가 설정하여 서버에 실제로 업로드된 파일명을 반환함. 파일명이 중복되면 변경된 파일명을 반환함 |
| getOriginalFileName(String name) |
String | 사용자가 업로드한 실제 파일명을 반환함. 파일명이 중복되면 변경 전의 파일명을 반환함 |
예제 7-1.MultipartRequest 클래스를 이용하여 파일 업로드 및 정보 출력하기
JSPBook/src/main/webapp/ch07/fileupload01.jsp
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>File Upload</title> </head> <body> <form name="fileForm" method="post" enctype="multipart/form-data" action="ch07_1"> <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_1_controller.java
|
package controller.ch07;
import java.io.File; import java.io.IOException; import java.util.Enumeration; import com.oreilly.servlet.MultipartRequest; import com.oreilly.servlet.multipart.DefaultFileRenamePolicy; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet("/ch07_1") public class ch07_1_controller extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher ds = req.getRequestDispatcher("ch07/fileupload01.jsp"); ds.forward(req, resp); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { //멀티파츠리퀘스트 객체를 생성 : WEB-INF>lib폴더에 라이브러리 확보 여부 중요(jar: 자바 아카이브 압축파일: class설계도) String save = request.getServletContext().getRealPath("resources/images"); //JSPBook 서버 주소 경로 System.out.println(save); MultipartRequest multi = new MultipartRequest(request, save, 5*1024*1024, "utf-8", new DefaultFileRenamePolicy()); //텍스트 가져오기 : key(HTML 태그의 name 속성)를 알 때 String name1 = multi.getParameter("name"); String subject1 = multi.getParameter("subject"); System.out.println(name1); System.out.println(subject1); //텍스트 가져오기 : key(HTML 태그의 name 속성)를 모를 때 /* Enumeration en = multi.getParameterNames(); while(en.hasMoreElements()) { String name2 = (String) en.nextElement(); String value = multi.getParameter(name2); System.out.println(name2 + ":" + value); } */ //이미지 정보 가져오기 : key(HTML 태그의 name 속성)를 알 때 String sysname = multi.getFilesystemName("filename"); String oriname = multi.getOriginalFileName("filename"); String type = multi.getContentType("filename"); File file = multi.getFile("filename"); System.out.println(sysname); System.out.println(oriname); System.out.println(type); System.out.println(file); //이미지 정보 가져오기 : key(HTML 태그의 name 속성)를 모를 때 /* Enumeration en2 = multi.getFileNames(); while(en2.hasMoreElements()) { String key = (String) en2.nextElement(); String sysname2 = multi.getFilesystemName(key); String oriname2 = multi.getOriginalFileName(key); String type2 = multi.getContentType(key); File file2 = multi.getFile(key); System.out.println(key); System.out.println(sysname2); System.out.println(oriname2); System.out.println(type2); System.out.println(file2); } */ } } |
*알 때/ 모를 때 따로 실행하기
실행 결과
1)알 때
|
D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images
홍길순 펭귄 pengun.jpg pengun.jpg image/jpeg D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images\pengun.jpg |
2)모를 때
|
D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images
name:홍길순 subject:펭귄 filename pengun.jpg pengun.jpg image/jpeg D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images\pengun.jpg |
![]() |
예제 7-2.MultipartRequest 클래스를 이용하여 여러 파일 업로드 및 정보 출력하기
JSPBook/src/main/webapp/ch07/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="ch07_2"> <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> |
ch07_2_controller.java
|
package controller.ch07;
import java.io.IOException; import com.oreilly.servlet.MultipartRequest; import com.oreilly.servlet.multipart.DefaultFileRenamePolicy; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet("/ch07_2") public class ch07_2_controller extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher ds = req.getRequestDispatcher("ch07/fileupload02.jsp"); ds.forward(req, resp); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { String save = request.getServletContext().getRealPath("resources/images"); //JSPBook 서버 주소 경로 System.out.println(save); 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"); String filename1 = multi.getFilesystemName("filename1"); String filename2 = multi.getFilesystemName("filename2"); String filename3 = multi.getFilesystemName("filename3"); System.out.println(name1); System.out.println(subject1); System.out.println(name2); System.out.println(subject2); System.out.println(name3); System.out.println(subject3); System.out.println(filename1); System.out.println(filename2); System.out.println(filename3); } } |
실행 결과
|
D:\SaveLocation\jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\JSPBook\resources\images
홍길순 튤립 홍길동 펭귄 수여인 하늘 flower.jpg pengun.jpg sky_blue.jpg |
![]() |
03.Commons-FileUpload를 이용한 파일 업로드
-파일 업로드 패키지인 Commons-FileUpload는 서버의 메모리상에서 파일 처리가 가능하도록 지원함. 이 패키지는 Commons-io 패키지를 바탕으로 작성되었기 때문에 웹 브라우저에서 서버로 파일을 업로드하기 위해 오픈 라이브러리 Commons-FileUpload.jar, Commons-io.jar 파일을 다음 배포 사이트에서 직접 다운로드해서 사용함. 그리고 JSP 페이지에 page 디렉티브 태그의 import 속성을 사용하여 패키지 org.apache.commoms.fileupload.*를 설정해야 함
·배포 사이트: http://commons.apache.org/downloads
·다운로드 파일: commons-fileupload-1.5.bin.zip, commons-io-2.13.0-bin.zip
-(1)Commons-FileUpload를 이용하여 파일을 업로드하려면 먼저 Commons-FileUpload 패키지에 포함되어 있는 DiskFileUpload 객체를 생성함 (2)생성된 객체를 통해 DiskFileUpload 클래스가 제공하는 메소드를 사용하여 웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 가져옴 (3)FileItem 클래스의 메소드를 사용하여 요청 파라미터가 일반 데이터인지 파일인지 분석 및 처리하여 파일을 업로드함
◎DiskFileUpload 클래스의 메소드
| 메소드 | 유형 | 설명 |
| setRepositoryPath(String repositotyPath) | void | 업로드된 파일을 임시로 저장할 디렉터리를 설정함 |
| setSizeMax(long sizeMax) | void | 최대 파일의 크기를 설정함 |
| setSizeThreshold(int sizeThreshold) | void | 메모리상에 저장할 최대 크기를 설정함 |
| parseRequest(HttpServletRequest reg) | List<FileItem> | multipart/form-data 유형의 요청 파라미터를 가져옴 |
◎FileItem 클래스의 메소드
| 메소드 | 유형 | 설명 |
| isFormField() | boolean | 요청 파라미터가 파일이 아니라 일반 데이터인 경우 true를 반환함 |
| getFieldName() | String | 요청 파라미터의 이름을 얻어옴 |
| getString() | String | 기본 문자 인코딩을 사용하여 요청 파라미터의 값을 얻어 옴 |
| getString(String encoding) | String | 설정한 문자 인코딩을 사용하여 요청 파라미터의 값을 얻어 옴 |
| getName() | String | 업로드된 파일(경로 포함)의 이름을 얻어옴 |
| getSize() | long | 업로드된 파일의 크기를 얻어옴 |
| get() | byte[] | 업로드된 파일을 바이트 배열로 얻어옴 |
| isInMemory | boolean | 업로드된 파일이 메모리에 저장된 상태인 경우 true를 반환하고, 임시 디렉터리에 저장된 경우 false를 반환함 |
| delete() | void | 파일과 관련된 자원을 삭제함. 메모리상에 저장된 경우 할당된 메모리를 반환하고, 임시 파일로 저장된 경우 파일을 삭제함 |
| write() | void | 파일과 관련된 자원을 저장함 |
| getContentType() | String | 웹 브라우저가 전송하는 콘텐츠 유형을 반환하고, 정의되어 있지 않은 경우 null을 반환함 |
◎FileItem 클래스로 업로드 파일을 저장하는 방법
(1)write() 메소드를 사용함
(2)getInputStream() 메소드로 입력 스트림으로부터 바이트 데이터를 가져와 FileOutputStream()을 사용하여 파일에 풀력함
(3)get() 메소드로 가져온 바이트 배열을 FileOutputStream을 사용하여 파일에 출력함
-write() 메소드는 주로 로컬 디스크에 직접 업로드한 파일을 저장할 때 사용하고, getInputStream()이나 get() 메소드는 업로드한 파일에 특별한 처리를 하거나 데이터베이스와 같이 디스크가 아닌 영역에 업로드한 파일을 저장할 때 사용함
예제 7-3.Commons-FileUpload를 이용하여 파일 업로드하기
JSPBook/src/main/webapp/ch07/fileupload03.jsp
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>File Upload</title> </head> <body> <form action="ch07_3" method="post" enctype="multipart/form-data"> <p> 파 일 : <input type="file" name="filename"> <p> <input type="submit" value="파일 올리기"> </form> </body> </html> |
ch07_3_controller.java
|
package controller.ch07;
import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.List; import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import com.oreilly.servlet.MultipartRequest; import com.oreilly.servlet.multipart.DefaultFileRenamePolicy; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet("/ch07_3") public class ch07_3_controller extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher ds = req.getRequestDispatcher("ch07/fileupload03.jsp"); ds.forward(req, resp); } @Override protected void doPost(HttpServletRequest requset, HttpServletResponse resp) throws ServletException, IOException { String fileUploadPath = requset.getServletContext().getRealPath("resources/images"); // JSPBook 서버 주소 경로 System.out.println(fileUploadPath); DiskFileUpload upload = new DiskFileUpload(); List items = null; Iterator params = null; try { items = upload.parseRequest(requset); //Request-> List 객체 바꿈: text, img params = items.iterator(); //이터레이터 주소주세요. } catch (FileUploadException e) { e.printStackTrace(); } while (params.hasNext()) { FileItem fileItem = (FileItem) params.next(); //next 반환: fileItem에 담기 if (!fileItem.isFormField()) { //~인지 아닌지 String fileName = fileItem.getName(); //이름 생성 fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); //이름 생성 File file = new File(fileUploadPath + "/" + fileName); //파일 생성 try { fileItem.write(file); //내용 삽입 } catch (Exception e) { e.printStackTrace(); } }else { String filedName = fileItem.getFieldName(); //key String fileName = fileItem.getString("utf-8"); //value } } } } |
실행 결과
![]() |
04.북마켓 도서 이미지 등록하기
-파일 업로드 처리 방법을 이용하여 도서 이미지를 등록할 수 있는 폼 페이지를 만들고 도서 이미지를 업로드하여 도서 이미지를 출력함
예제7-5.정적 리소스(도서 이미지 및 부트스트랩 CSS) 관리하기
BookMarket/src/main/java/dto/Book.java
1)도서 클래스에 멤버 변수 추가하기
|
package dto;
import java.io.Serializable; public class Book implements Serializable{ private static final long serialVersionUID=-4274700572038677000L; private String bookId; //도서 ID private String name; //도서명 private int unitPrice; //가격 private String Author; //저자 private String description; //설명 private String publisher; //출판사 private String category; //분류 private long unitsInStock; //재고개수 private String releaseDate; //출판일(월/년) private String condition; //신제품 or 구제품 or 리퍼브제품 -------------------------- 추가 ------------------------------- private String filename; //이미지 파일명 |
2)추가된 멤버 변수의 Setter/Getter() 메소드 작성하기
| public Book() { super(); } public Book(String bookId, String name, int unitPrice) { super(); this.bookId = bookId; this.name = name; this.unitPrice = unitPrice; } public String getBookId() { return bookId; } public void setBookId(String bookId) { this.bookId = bookId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getUnitPrice() { return unitPrice; } public void setUnitPrice(int unitPrice) { this.unitPrice = unitPrice; } public String getAuthor() { return Author; } public void setAuthor(String author) { Author = author; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } 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 getReleaseDate() { return releaseDate; } public void setReleaseDate(String releaseDate) { this.releaseDate = releaseDate; } public String getCondition() { return condition; } public void setCondition(String condition) { this.condition = condition; } public static long getSerialversionuid() { return serialVersionUID; } -------------------------- 추가 ------------------------------- public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } } |
3)도서 데이터 접근 클래스 수정하기(확장자(이미지)추가)
BookMarket/src/main/java/dao/BookRepository.java
|
package dao;
import dto.Book; import java.util.ArrayList; public class BookRepository { private ArrayList<Book> listOfBooks = new ArrayList<Book>(); private static BookRepository instance = new BookRepository(); //싱글톤 public static BookRepository getInstance() { return instance; } public BookRepository() { // System.out.println("BookRepository 객체가 생성됨"); Book book1 = new Book("ISBN1234", "C# 프로그래밍", 27000); book1.setAuthor("우재남"); book1.setDescription( "C#을 처음 접하는 독자를 대상으로 일대일 수업처럼 자세히 설명한 책이다. 꼭 알아야 할 핵심 개념은 기본 예제로 최대한 쉽게 설명했으며, 중요한 내용은 응용 예제, 퀴즈, 셀프 스터디, 예제 모음으로 한번 더 복습할 수 있다."); book1.setPublisher("한빛아카데미"); book1.setCategory("IT모바일"); book1.setUnitsInStock(1000); book1.setReleaseDate("2022/10/06"); -------------------------- 추가 ------------------------------- book1.setFilename("ISBN1234.jpg"); Book book2 = new Book("ISBN1235", "자바마스터", 30000); book2.setAuthor("송미영"); book2.setDescription( "자바를 처음 배우는 학생을 위해 자바의 기본 개념과 실습 예제를 그림을 이용하여 쉽게 설명합니다. 자바의 이론적 개념→기본 예제→프로젝트 순으로 단계별 학습이 가능하며, 각 챕터의 프로젝트를 실습하면서 온라인 서점을 완성할 수 있도록 구성하였습니다."); book2.setPublisher("한빛아카데미"); book2.setCategory("IT모바일"); book2.setUnitsInStock(1000); book2.setReleaseDate("2023/01/01"); book2.setFilename("ISBN1235.jpg"); Book book3 = new Book("ISBN1236", "파이썬 프로그래밍", 30000); book3.setAuthor("최성철"); book3.setDescription( "파이썬으로 프로그래밍을 시작하는 입문자가 쉽게 이해할 수 있도록 기본 개념을 상세하게 설명하며, 다양한 예제를 제시합니다. 또한 프로그래밍의 기초 원리를 이해하면서 파이썬으로 데이터를 처리하는 기법도 배웁니다."); book3.setPublisher("한빛아카데미"); book3.setCategory("IT모바일"); book3.setUnitsInStock(1000); book3.setReleaseDate("2023/01/01"); book3.setFilename("ISBN1236.jpg"); listOfBooks.add(book1); listOfBooks.add(book2); listOfBooks.add(book3); } public ArrayList<Book> getAllBooks() { return listOfBooks; } public Book getBookById(String bookId) { Book bookById=null; for(int i=0; i<listOfBooks.size(); i++) { Book book=listOfBooks.get(i); if(book!=null && book.getBookId()!=null && book.getBookId().equals(bookId)) { bookById=book; break; } } return bookById; } public void addBook(Book book) { //DTO listOfBooks.add(book); } } |
4)정적 리소스 관리 폴더 만들기
-/scr/main/webapp/ 폴더에 resources 폴더를 생성하고, 여기에 이미지 파일을 관리하는 images 폴더와 부트스트랩 파일(bootstrap.css)을 관리하는 css 폴더를 생성함
-images 폴더에 이미지 파일명을 도서 아이디로 하여 등록함
-css 폴더에 부트스트랩 CSS 파일(bootstrap.min.css)을 다운로드하여 등록함
![]() |
◎부트스트랩 CSS 파일 설치 방법
(1)배포 사이트(http://getbootstrap.com/)에서 bootstrap-5.3.0-dist.zip 파일을 다운로드함
(2)bootstrap-5.3.0-dist.zip 파일의 압축을 품
(3)압축을 푼 파일의 css 폴더에 있는 bootstrap.min.css 파일을 찾음
(4)웹 애플리케이션의 /src/main/webapp/resources/css/ 폴더에 bootstrap.min.css 파일을 포함함
5)도서 목록 페이지 수정하기
BookMarket/src/main/webapp/books.jsp
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.ArrayList" %> <%@ page import="dto.Book" %> <%@ page import="dao.BookRepository" %> <!-- BookRepository bookDAO = new BookRepository() --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://kit.fontawesome.com/fa848000d2.js" crossorigin="anonymous"></script> -------------------------- 추가 ------------------------------- <link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" /> <title>도서 목록</title> </head> <body> <div class="container py-4"> <%@ include file="menu.jsp" %> <div class="p-5 mb-4 bg-body-tertiary rounded-3"> <div class="container-fluid py-5"> <h1 class="display-5 fw-bold">도서목록</h1> <p class="col=md-8 fs-4">BookList</p> </div> </div> <% BookRepository dao=BookRepository.getInstance(); ArrayList<Book> listOfBooks = dao.getAllBooks(); %> <div class="row align-items-md-stretch text-center"> <% for(int i=0; i<listOfBooks.size(); i++){ Book book=listOfBooks.get(i); %> <div class="col-md-4"> <div class="h-100 p-2 round-3"> -------------------------- 추가 ------------------------------- <img src="./resources/images/<%=book.getFilename()%>" style="width: 250px; height:350px" /> <p><h5><b><%=book.getName() %></b></h5> <p> <%=book.getAuthor() %> <br><%=book.getPublisher() %> : <%=book.getUnitPrice() %>원 <p> <%=book.getDescription() %> <p><%=book.getUnitPrice() %>원 <p> <a href="./book.jsp?id=<%=book.getBookId() %>" class="btn btn-secondary" role="button">상세 정보 »</a> </div> </div> <% } %> </div> <%@ include file="footer.jsp" %> </div> </body> </html> |
*style에 px 안쓰면 이미지 크기 안 먹힘
6)도서 상세 정보 페이지 수정하기
BookMarket/src/main/webapp/book.jsp
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <%@ page import="dto.Book" %> <%@ page import="dao.BookRepository" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://kit.fontawesome.com/fa848000d2.js" crossorigin="anonymous"></script> -------------------------- 추가 ------------------------------- <link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" /> <title>도서 상세 정보</title> </head> <body> <div class="container py-4"> <%@ include file="menu.jsp" %> <div class="p-5 mb-4 bg-body-tertiary rounded-3"> <div class="container-fluid py-5"> <h1 class="display-5 fw-bold">도서정보</h1> <p class="col-md-8 fs-4">BookInfo</p> </div> </div> <% String id=request.getParameter("id"); BookRepository dao=BookRepository.getInstance(); Book book=dao.getBookById(id); %> <div class="row align-items-md-stretch"> -------------------------- 추가 ------------------------------- <div class="col-md-5"> <img src="./resources/images/<%=book.getFilename() %>" style="width : 70%"> </div> <div class="col-md-12"> <h3><b><%=book.getName() %></b></h3> <p> <%=book.getDescription() %> <p> <b>도서코드 : </b><span class="badge text-bg-danger"> <%= book.getBookId()%></span> <p> <b>저자</b> : <%=book.getAuthor() %> <p> <b>출판사</b> : <%=book.getPublisher() %> <p> <b>출판일</b> : <%=book.getReleaseDate() %> <p> <b>분류</b> : <%=book.getCategory() %> <p> <b>재고수</b> : <%=book.getUnitsInStock() %> <h4><%=book.getUnitPrice() %>원</h4> <p> <a href="#" class="btn btn-info">도서주문 »</a> <a href=" ./books.jsp" class="btn btn-secondary" >도서 목록 »</a> </div> </div> <jsp:include page="footer.jsp" /> </div> </body> </html> |
예제 7-6.도서 이미지 업로드 하기
1)오픈 라이브러리 cos.jar 등록하기
-MultipartRequest 클래스를 이용한 파일 업로드를 위해 /src/main/webapp/WEB-INF/lib/ 폴더에 cos.jar 파일을 등록함
![]() |
*cos.jar 파일은 톰캣 10버전에서 사용할 수 있도록 마이그레이션해야 함
2)도서 정보 등록 페이지 수정하기
BookMarket/src/main/webapp/addBook.jsp
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://kit.fontawesome.com/fa848000d2.js" crossorigin="anonymous"></script> -------------------------- 추가 ------------------------------- <link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" /> <title>도서 등록</title> </head> <body> <div class="container py-4"> <%@ include file="menu.jsp"%> <div class="p-5 mb-4 bg-body-tertiary rounded-3"> <div class="container-fluid py-5"> <h1 class="display-5 fw-bold">도서 등록</h1> <p class="col-md-8 fs-4">Book Addition</p> </div> </div> <div class="row align-items-md-stretch"> -------------------------- 추가 ------------------------------- <form name="newBook" action="./processAddBook.jsp" class="form-horizontal" method="post" enctype="multipart/form-data"> <div class="mb-3 row"> <label class="col-sm-2">도서코드</label> <div class="col-sm-3"> <input type="text" name="bookId" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">도서명</label> <div class="col-sm-3"> <input type="text" name="name" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">가격</label> <div class="col-sm-3"> <input type="text" name="unitPrice" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">저자</label> <div class="col-sm-3"> <input type="text" name="author" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">출판사</label> <div class="col-sm-3"> <input type="text" name="publisher" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">출판일</label> <div class="col-sm-3"> <input type="text" name="releaseDate" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">상세정보</label> <div class="col-sm-5"> <textarea name="description" cols="50" rows="2" class="form-control" placeholder="100자 이상 적어주세요"></textarea> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">분류</label> <div class="col-sm-3"> <input type="text" name="category" class="form-control"> </div> </div> <div class="mb-3 row"> <label class="col-sm-2">재고수</label> <div class="col-sm-3"> <input type="text" name="unitsInStock" class="form-control"> </div> </div> <div class="mb-3 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="EBook"> E-Book </div> </div> -------------------------- 추가 ------------------------------- <div class="mb-3 row"> <label class="col-sm-2">이미지</label> <div class="col-sm-5"> <input type="file" name="BookImage" class="form-control"> </div> </div> <div class="mb-3 row"> <div class="col-sm-offset-2 col-sm-10"> <input type="submit" class="btn btn-primary" value="등록"> </div> </div> </form> </div> <jsp:include page="footer.jsp" /> </div> </body> </html> |
3)도서 등록 처리 페이지 수정하기
BookMarket/src/main/webapp/processAddBook.jsp
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <%@ page import="dto.Book" %> <%@ page import="dao.BookRepository" %> -------------------------- 추가 ------------------------------- <%@ page import="com.oreilly.servlet.*" %> <%@ page import="com.oreilly.servlet.multipart.*" %> <%@ page import="java.util.*" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% request.setCharacterEncoding("UTF-8"); -------------------------- 추가 ------------------------------- String realFolder=request.getServletContext().getRealPath("resources/images"); int maxSize=5 * 1024 * 1024; //최대 업로드될 파일의 크기 5MB String encType="utf-8"; //인코딩 유형 MultipartRequest multi=new MultipartRequest(request, realFolder, maxSize, encType, new DefaultFileRenamePolicy()); String bookId=multi.getParameter("bookId"); String name=multi.getParameter("name"); String unitPrice=multi.getParameter("unitPrice"); String author=multi.getParameter("author"); String publisher=multi.getParameter("publisher"); String releaseDate=multi.getParameter("releaseDate"); String description=multi.getParameter("description"); String category=multi.getParameter("category"); String unitsInStock=multi.getParameter("unitsInStock"); String condition=multi.getParameter("condition"); -------------------------- 추가 ------------------------------- String fileName=multi.getFilesystemName("BookImage"); System.out.println(bookId); System.out.println(name); System.out.println(unitPrice); System.out.println(publisher); System.out.println(releaseDate); System.out.println(description); System.out.println(category); System.out.println(unitsInStock); System.out.println(condition); System.out.println(fileName); Integer price; if(unitPrice.isEmpty()) price=0; else price=Integer.valueOf(unitPrice); long stock; if(unitsInStock.isEmpty()) stock=0; else stock=Long.valueOf(unitsInStock); BookRepository dao=BookRepository.getInstance(); Book newBook=new Book(); newBook.setBookId(bookId); newBook.setName(name); newBook.setUnitPrice(price); newBook.setAuthor(author); newBook.setPublisher(publisher); newBook.setReleaseDate(releaseDate); newBook.setDescription(description); newBook.setCategory(category); newBook.setUnitsInStock(stock); newBook.setCondition(condition); -------------------------- 추가 ------------------------------- newBook.setFilename(fileName); dao.addBook(newBook); response.sendRedirect("books.jsp"); %> </body> </html> |
*setParameter("")를 multi.getParameter("");로 변경
'벡엔드 웹프로그래밍 > JSP' 카테고리의 다른 글
| JSP 웹프로그래밍 64일차 (25/2/17) (0) | 2025.02.17 |
|---|---|
| JSP 웹프로그래밍 63일차 (25/2/14) (0) | 2025.02.14 |
| JSP 웹프로그래밍 61일차 (25/2/12) (0) | 2025.02.12 |
| JSP 웹프로그래밍 60일차 (25/2/11) (2) | 2025.02.11 |
| JSP 웹프로그래밍 59일차 (25/2/10) (2) | 2025.02.10 |




