[쉽게 배우는 JSP 웹 프로그래밍] 7장 정리, 연습문제
JSP에서 파일 업로드를 처리하는 방법에 대해 설명하고 있으며, 이는 폼 태그 작성의 중요한 규칙과 cos.jar 혹은 commons-fileupload.jar의 사용을 포함한다. MultipartRequest와 Commons-FileUpload를 사용한 파일 업로드 방법이 상세히 설명되어 있으며, 이를 통해 웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 처리하고 파일을 업로드하는 방법을 배울 수 있다.
Feb 22, 2024
7장 정리
fileUpload01.jsp
<%@ page contentType="text/html; charset=utf-8"%> <html> <head> <title>File Upload</title> </head> <body> <form name="fileForm" method="post" enctype="multipart/form-data" action="fileUpload03_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>
fileUpload01_process.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="java.io.*"%> <% MultipartRequest multi = new MultipartRequest(request, "C:\\upload", 5 * 1024 * 1024, "utf-8", new DefaultFileRenamePolicy()); 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>"); 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>"); } } %>
fileUpload03_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 fileUploadPath = "C:\\upload"; DiskFileUpload upload = new DiskFileUpload(); upload.setSizeMax(1000000); upload.setSizeThreshold(4096); upload.setRepositoryPath(fileUploadPath); List<FileItem> items = upload.parseRequest(request); for (FileItem f : items) { if (f.isFormField()) { String name = f.getFieldName(); String value = f.getString("utf-8"); out.println(name + "=" + value + "<br>"); } else { System.out.println(f); String fileFieldName = f.getFieldName(); String fileName = f.getName(); String contentType = f.getContentType(); fileName = fileName.substring(fileName.lastIndexOf("\\")+ 1); long fileSize = f.getSize(); File file = new File(fileUploadPath + "/" + fileName); f.write(file); out.println("-------------------------<br>"); out.println("요청 파라미터 이름 : " + fileFieldName + "<br>"); out.println("저장 파일 이름 : " + fileName + "<br>"); out.println("파일 콘텐츠 유형 : " + contentType + "<br>"); out.println("파일 크기 : " + fileSize); } } %> </body> </html>
핵심 키워드
- 웹 브라우저에서 서버로 파일을 전송하기 위해 JSP 페이지에 폼 태그를 작성할 때 몇 가지 중요한 규칙이 있다.
- form 태그의 method 속성은 반드시 POST 방식으로 설정해야 한다.
- form 태그의 enctype 속성은 반드시 multipart/form-data로 설정해야 한다.
- form 태그의 action 속성은 파일 업로드를 처리할 JSP 파일로 설정해야 한다.
- 파일 업로드를 위해 input 태그의 type 속성을 file로 설정해야 한다. 만약 여러 파일을 업로드하러면 2개 이상의 input 태그를 사용하고 name 속성에 서로 다른 값을 설정한다.
- 웹 브라우저에서 서버로 파일 업로드를 처리하려면 단순한 자바 코드로 작성할 수 없으므로 cos.jar나 commons-fileupload.jar를 사용해야 한다.
- MultipartRequest는 cos 패키지에 포함되어 있는 파일 업로드 컴포넌트로, 웹 페이지에서 서버로 업로드되는 파일 자체만 다루는 클래스다.
- MultipartRequest 클래스를 이용하여 파일을 업로드하려면 먼저 MultipartRequest 객체를 생성한다. 그리고 생성된 객체를 통해 MultipartRequest 클래스가 제공하는 메소드를 사용하여 웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 읽어오고 파일을 업로드한다.
- Commons-FileUpload는 Commons-io 패키지를 바탕으로 작성된, 서버의 메모리상에서 파일 처리가 가능한 파일 업로드 패키지다.
- Commons-FileUpload를 이용해 파일을 업로드하려면 먼저 Commons-FileUpload 패키지에 포함되어 있는 DiskFileUpload 객체를 생성한다.
- 생성된 객체를 통해 DiskFileUpload 클래스가 제공하는 메소드를 사용하여 웹 브라우저가 전송한 multipart/form-data 유형의 요청 파라미터를 가져온다.
- 그리고 FileItem 클래스의 메소드를 사용하여 요청 파라미터가 일반 데이터인지 파일인지 분석 및 처리하여 파일을 업로드한다.
연습문제
practice01.jsp
01 method 속성은 post로 설정한다. enctype 속성은 multipart/form-data로 설정한다. action 속성은 파일 업로드를 처리할 JSP 파일로 설정한다. input 태그의 type 속성을 file로 설정한다. 만약 여러 파일을 업로드하려면 2개 이상의 input 태그를 사용하고 name 속성에 서로 다른 값을 설정한다. 02 웹브라우저에서 파일을 업로드하려면 단순한 자바코드로 작성해서 처리할 수 없으므로 cos.jar나 commons-fileupload.jar를 이용해서 파일 업로드를 처리한다.
practice03.jsp
<%@ page contentType="text/html; charset=utf-8"%> <html> <head> <title>File Upload</title> </head> <body> <form name="fileForm" method="post" enctype="multipart/form-data" action="practice03_process.jsp"> <p> 파 일 :<input type="file" name="filename"> <p><input type="submit" value="파일 올리기"> </form> </body> </html>
practice03_process.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="java.io.*"%> <% MultipartRequest multi = new MultipartRequest(request, "C:\\upload", 5 * 1024 * 1024, "utf-8", new DefaultFileRenamePolicy()); 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>"); } 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>"); } } %>
practice04.jsp
<%@ page contentType="text/html; charset=utf-8"%> <html> <head> <title>File Upload</title> </head> <body> <form name="fileForm" method="post" enctype="multipart/form-data" action="practice04_process.jsp"> <p> 파 일 :<input type="file" name="filename"> <p><input type="submit" value="파일 올리기"> </form> </body> </html>
practice04_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 fileUploadPath = "C:\\upload"; DiskFileUpload upload = new DiskFileUpload(); upload.setSizeMax(1000000); upload.setSizeThreshold(4096); upload.setRepositoryPath(fileUploadPath); List<FileItem> items = upload.parseRequest(request); for (FileItem f : items) { if (f.isFormField()) { String name = f.getFieldName(); String value = f.getString("utf-8"); out.println(name + "=" + value + "<br>"); } else { String fileFieldName = f.getFieldName(); String fileName = f.getName(); String contentType = f.getContentType(); fileName = fileName.substring(fileName.lastIndexOf("\\")+ 1); long fileSize = f.getSize(); File file = new File(fileUploadPath + "/" + fileName); f.write(file); out.println("-------------------------<br>"); out.println("요청 파라미터 이름 : " + fileFieldName + "<br>"); out.println("저장 파일 이름 : " + fileName + "<br>"); out.println("파일 콘텐츠 유형 : " + contentType + "<br>"); out.println("파일 크기 : " + fileSize); } } %> </body> </html>
practice05
BookRepository.java
package dao; import java.util.ArrayList; import dto.Book; public class BookRepository { private ArrayList<Book> listOfBooks = new ArrayList<Book>(); public static BookRepository instance = new BookRepository(); public static BookRepository getInstance() { return instance; } public BookRepository() { Book book1 = new Book("ISBN0001", "HTML5+CSS3", 15000); book1.setAuthor("황재호"); book1.setDescription( "워드나 PPT 문서를 만들 수 있나요? 그러면 문제 없습니다. 지금 바로 웹페이지 제작에 도전해보세요. 지금 당장 컴퓨터가 없어도 괜찮습니다. 코드와 실행 화면에 바로 보여서 눈으로만 읽어도 쉽게 파악할 수 있는 것은 기본이고, 중간중간 퀴즈를 추가하여 재미있게 게임하듯 복습할 수 있습니다."); book1.setPublisher("한빛미디어"); book1.setCategory("Hello Coding"); book1.setUnitsInStock(1000); book1.setTotalPages(288); book1.setReleaseDate("2018/03/02"); book1.setCondition("신규 도서"); book1.setFilename("ISBN0001.jpg"); Book book2 = new Book("ISBN0002", "쉽게 배우는 자바 프로그래밍", 27000); book2.setAuthor("우종종"); book2.setDescription( "객체 지향의 핵심과 자바의 현대적 기능을 충실히 다루면서도 초보가자 쉽게 학습할 수 있게 구성했습니다. 시각화 도구를 활용한 개념 셜명과 군더더기 없는 핵심 코드를 통해 개념과 구현 두 마리 토끼를 잡아보세요."); book2.setPublisher("한빛아카데미"); book2.setCategory("IT모바일"); book2.setUnitsInStock(10000); book2.setTotalPages(2888); book2.setReleaseDate("2018/03/03"); book2.setCondition("중고 도서"); book2.setFilename("ISBN0002.jpg"); Book book3 = new Book("ISBN0003", "스프링4 입문", 27000); book3.setAuthor("하세가와 유이치, 오오노 와타루, 토키 코헤이,(권은철, 전민수)"); book3.setDescription( "스프링은 단순히 사용 방법만 익히는 것보다 아키텍쳐를 어떻게 이해하고 설계하는지가 더 중요합니다. 예제를 복사해 붙여넣는 식으로는 실제 개발에서 스프링을 제대로 활용할 수 없습니다. 스프링은 단순히 사용 방법만 익히는 것보다 아키텍쳐를 어떻게 이해하고 설계하는지가 더 중요합니다."); book3.setPublisher("한빛미디어"); book3.setCategory("IT모바일"); book3.setUnitsInStock(100); book3.setTotalPages(228); book3.setReleaseDate("2018/03/04"); book3.setCondition("E-Book"); book3.setFilename("ISBN0003.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) { listOfBooks.add(book); } }
Book.java
package dto; import java.io.Serializable; public class Book implements Serializable { private static final long serialVersionUID = -8581217587295757890L; private String bookId; private String name; private Integer unitPrice; private String author; private String description; private String publisher; private String category; private long unitsInStock; private long totalPages; private String releaseDate; private String condition; private String filename; public Book() { super(); } public Book(String bookId, String name, Integer 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 Integer getUnitPrice() { return unitPrice; } public void setUnitPrice(Integer unitPrice) { this.unitPrice = unitPrice; } public String getAuthor() { return author; } public void setAuthor(String author) { this.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 long getTotalPages() { return totalPages; } public void setTotalPages(long totalPages) { this.totalPages = totalPages; } 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 String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } }
Books.jsp
<%@ page contentType="text/html; charset=utf-8"%> <%@ page import="java.util.ArrayList"%> <%@ page import="dto.Book"%> <jsp:useBean id="bookDAO" class="dao.BookRepository" 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> <% ArrayList<Book> listOfBooks = bookDAO.getAllBooks(); %> <div class="container"> <div class="text-left"> <% for (int i = 0; i < listOfBooks.size(); i++) { Book book = listOfBooks.get(i); System.out.println(book.getFilename()); %> <img src="/upload/<%=book.getFilename()%>" style="width: 100%"> <h3><%="[" + book.getCategory() + "]" + book.getName()%></h3> <p><%=book.getDescription()%> <p><%=book.getAuthor() + " | " + book.getPublisher() + " | " + book.getUnitPrice() + "원"%> <p> <a href="./product.jsp?id=<%=book.getBookId()%>" class="btn btn-secondary" role="button">상세 정보 »</a> </div> <hr> <% } %> </div> <jsp:include page="footer.jsp" /> </body> </html>
addBook.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"> <label class="col-sm-2">도서코드</label> <div class="col-sm-3"> <input type="text" name="bookId" 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"> <input type="text" name="author" 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="publisher" 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="releaseDate" 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="totalPages" 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="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 "> E-Book </div> </div> <div class="form-group row"> <label class="col-sm-2">이미지</label> <div class="col-sm5"> <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="등록"> </div> </div> </form> </div> </body> </html>
processAddBook.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.Book"%> <%@ page import="dao.BookRepository"%> <% request.setCharacterEncoding("UTF-8"); String filename = ""; String realFolder = "C:\\upload"; int maxSize = 5 * 1024 * 1024; String encType = "UTF-8"; MultipartRequest multi = new MultipartRequest(request, realFolder, maxSize, encType, new DefaultFileRenamePolicy()); String bookId = request.getParameter("bookId"); String name = request.getParameter("name"); String unitPrice = request.getParameter("unitPrice"); String author = request.getParameter("author"); String description = request.getParameter("description"); String publisher = request.getParameter("publisher"); String category = request.getParameter("category"); String unitsInStock = request.getParameter("unitsInStock"); String totalPages = request.getParameter("totalPages"); String releaseDate = request.getParameter("releaseDate"); String condition = request.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); long pages; if (unitsInStock.isEmpty()) pages = 0; else pages = Long.valueOf(totalPages); Enumeration files = multi.getFileNames(); String fname = (String) files.nextElement(); String fileName = multi.getFilesystemName(fname); BookRepository dao = BookRepository.getInstance(); Book newProduct = new Book(); newProduct.setBookId(bookId); newProduct.setName(name); newProduct.setUnitPrice(price); newProduct.setAuthor(author); newProduct.setDescription(description); newProduct.setPublisher(publisher); newProduct.setCategory(category); newProduct.setUnitsInStock(stock); newProduct.setTotalPages(pages); newProduct.setReleaseDate(releaseDate); newProduct.setCondition(condition); newProduct.setFilename(fileName); dao.addBook(newProduct); response.sendRedirect("products.jsp"); %>
product.jsp
<%@ page contentType="text/html; charset=utf-8"%> <%@ page import="dto.Book"%> <%@ page import="dao.BookRepository"%> <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"); BookRepository dao = BookRepository.getInstance(); Book book = dao.getBookById(id); %> <div class="container"> <div class="row"> <div class="col-md-5"> <img src="/upload/<%=book.getFilename()%>" style="width: 100%"> </div> <div class="col-md-6"> <h3><%=book.getName()%></h3> <p><%=book.getDescription()%> <p> <b>도서 코드 : </b><span class="badge badge-danger"> <%=book.getBookId()%></span> <p> <b>출판사</b> : <%=book.getPublisher()%> <p> <b>저자</b> : <%=book.getAuthor()%> <p> <b>재고 수</b> : <%=book.getUnitsInStock()%> <p> <b>총 페이지 수</b> : <%=book.getTotalPages()%> <p> <b>출판일</b> : <%=book.getReleaseDate()%> <h4><%=book.getUnitPrice()%>원 </h4> <p> <a href="#" class="btn btn-info"> 도서 주문 »</a> <a href="./books.jsp" class="btn btn-secondary">도서 목록 »</a> </div> </div> <hr> </div> <jsp:include page="footer.jsp" /> </body> </html>
결론
해당 코드를 작성하면서 JSP에서 파일 업로드의 개념과 특징, MultipartRequest를 이용한 파일 업로드 방법, Commons-FileUpload를 이용한 파일 업로드 방법을 익힐 수 있었다.
Share article