728x90
300x250

[Spring-Framework] 12. 파일 업로드 구현하기, C태그 사용(if, else, foreach)


Spring-Framework로 파일 업로드 구현하는 방법에 대해서 소개하겠다.


[작업 환경]

* 웹 서버: Apache-tomcat-9.0.37-windows-x64

* IDE: Spring-Tool-Suite 4-4.7.2. Releases.

* Eclipse Marketplace: STS 검색 후 Spring Tools 3 Add-On for Spring Tools 4 3.9.14.Release 설치할 것

* POM 라이브러리: 

  - Apache Commons IO 2.8.0 (2020. 09)

  - Apache Commons FileUpload (2018. 12)

* C태그(JSTL)





1. Eclipse Marketplace 설치하기


help -> eclipse marketplace를 클릭한다.



그림 1. Spring Tools 3 Add-On for Spring Tools 4 3.9.14. Releases 설치하기





2. pom.xml 설정하기


http://mvnrepository.com 사이트에 접속한다.



그림 2. MVN-Repository (검색어: common-io)


검색은 "common-io"를 검색한다.



그림 3. Apache Commons IO - 2.8.0


최신 2.8.0을 클릭하여 pom을 복사한다. (maven)



그림 4. MVN-Repository (검색어: commons-fileupload)


검색은 "commons-fileupload"를 검색한다.





그림 5. Apache Commons FileUpload (1.4)


최신 1.4를 클릭하여 pom을 복사한다. (maven)



그림 6. MVN-Repository (검색어: servlet)


검색은 "Java Servlet API"를 검색한다.



그림 7. Java Servlet API (2018. 4)


최신 4.0.1을 클릭하여 pom을 복사한다. (maven)




그림 8. pom.xml 파일 수정하기


javax.servlet은 버전을 바꿔준다.

commons-io, commons-fileupload는 추가해준다.


(중략)

<!-- Servlet -->

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->

<dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>javax.servlet-api</artifactId>

    <version>4.0.1</version>

    <scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.servlet.jsp</groupId>

<artifactId>jsp-api</artifactId>

<version>2.1</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->

<dependency>

    <groupId>commons-io</groupId>

    <artifactId>commons-io</artifactId>

    <version>2.8.0</version>

</dependency>

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->

<dependency>

    <groupId>commons-fileupload</groupId>

    <artifactId>commons-fileupload</artifactId>

    <version>1.4</version>

</dependency>


(중략)


* 파일명: pom.xml



3. web.xml - Servlet 2.5 스팩 -> 3.1 스팩으로 변경하기


스팩 정보에 관한 것이다.

Spring Legacy Project의 Spring MVC Project를 생성하면, servlet 2.5버전의 web.xml가 생성되는 것을 확인할 수 있다.

Spec 2.5에서 Spec 3.1로 변경해줘야 한다.



그림 9. web.xml (servlet 2.5 -> servlet 3.1 스팩으로 변경 전)



그림 10. web.xml (servlet 2.5 -> servlet 3.1 스팩으로 변경 후)


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

version="3.1">


(중략)


* 파일명: web.xml (servlet 3.1 스팩)



4. context-common.xml - 생성하기


context-common.xml을 하나 만들어주겠다. 만드는 이유는 파일 업로드 관련해서 만드는 것이다.


경로: /src/main/webapp/WEB-INF/spring/appServlet/



그림 11. appServlet 폴더에서 마우스 오른쪽 버튼 모습


"appServlet 폴더에서 오른쪽 버튼" -> "New" -> "File"을 클릭한다.



그림 12. context-common.xml 파일 만들기


file명은 context-common.xml이라고 입력한 후 Finish를 누른다.



그림 13. context-common.xml 파일 수정하기


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:context="http://www.springframework.org/schema/context" 

xmlns:p="http://www.springframework.org/schema/p" 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns="http://www.springframework.org/schema/beans" 

xmlns:mvc="http://www.springframework.org/schema/mvc" 

xmlns:cache="http://www.springframework.org/schema/cache" 

xmlns:aop="http://www.springframework.org/schema/aop" 

xsi:schemaLocation="http://www.springframework.org/schema/beans 

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

http://www.springframework.org/schema/context 

http://www.springframework.org/schema/context/spring-context-3.0.xsd 

http://www.springframework.org/schema/mvc 

http://www.springframework.org/schema/mvc/spring-mvc.xsd 

http://www.springframework.org/schema/cache 

http://www.springframework.org/schema/cache/spring-cache.xsd">

<!-- MultipartResolver 설정 --> 

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 

<property name="maxUploadSize" value="100000000" /> 

<property name="maxInMemorySize" value="100000000" /> 

</bean>

</beans>


* 파일명: context-common.xml


[첨부(Attachments)]

context-common.zip


[비고]

파일 크기의 제한을 두기 위한 코드이다.

예: 최대 업로드 파일 크기는 20MB, 메모리에 최대로 저장할 수 있는 파일 크기는 10MB로 제한함.

1MB = 1,024KB

10MB = 10,485,760KB(1,024*1,024*10)

20MB = 20,971,520KB(1,024*1,024*20)



5. web.xml - context-common.xml 파일 인식시켜주기


web.xml을 연다.



그림 14. web.xml 수정 모습


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

version="3.1">


<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring/root-context.xml</param-value>

</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>


<!-- Processes application requests -->

<servlet>

<servlet-name>appServlet</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>

/WEB-INF/spring/appServlet/servlet-context.xml

/WEB-INF/spring/appServlet/context-common.xml

</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>appServlet</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>



<!-- UTF-8 -->

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>

org.springframework.web.filter.CharacterEncodingFilter

</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param> <init-param>

<param-name>forceEncoding</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

</web-app>



파일명: web.xml


[첨부(Attachments)]

web.zip



6. (직접 파일구현에 있어서 연관이 있는지?): 아니다.

MemberVO.java


* 패키지 경로: com.example.postget.vo


package com.example.postget.vo;


public class MemberVO {


private int num;

private String id;

private String passwd;

private String address;

public int getNum() {

return num;

}

public void setNum(int num) {

this.num = num;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getPasswd() {

return passwd;

}

public void setPasswd(String passwd) {

this.passwd = passwd;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

}



파일명: MemberVO.java


[첨부(Attachments)]

MemberVO.zip




7. Controller와 View 영역


지금 작업부터는 사용자 관점에서 파일 업로드를 구현하면 된다.

어떠한 작업을 할 것인지 개략적인 프로세스로 살펴보겠다.



그림 15. 프로세스 정의 - 파일 업로드


[첨부(Attachments)]

process.zip

process.pptx




8. Controller - BoardController.java 설정하기


POST 방식으로 /board/uploadResult를 호출하면, 파일 업로드 프로세스를 처리해주는 과정이 담긴 코드이다.

물론 루트 경로 등은 따로 별도로 재정의를 해서 사용하면 좋을 듯 싶다.

여력이 되면, 수정해봐도 좋을 듯 하다.


* 패키지 경로: com.example.postget.controller



그림 16, 그림 17. BoardController의 업로드 핵심 내용


POST 방식으로 업로드 처리에 관한 것이다.


(중략)


@RequestMapping(value = "uploadResult", method = RequestMethod.POST)

public String uploadResult(Model model, MemberVO memberVO, MultipartHttpServletRequest request) {

     // 루트 경로

           String rootUploadDir = "C:"+File.separator+"Upload"; // C:/Upload

           File dir = new File(rootUploadDir + File.separator + "testfile"); 

        

           if(!dir.exists()) { //업로드 디렉토리가 존재하지 않으면 생성

                dir.mkdirs();

           }

     Iterator<String> iterator = request.getFileNames(); // 다중 업로드 지원

           ArrayList<String> list = new ArrayList<String>();

        

           int fileLoop = 0;

           String uploadFileName;

           MultipartFile mFile = null;

           String orgFileName = ""; // 진짜 파일명

           String sysFileName = ""; // 변환된 파일명

        

            list.add("루트경로:" + dir + File.separator );

        

            while(iterator.hasNext()) {

       

                 fileLoop++;

            

                 uploadFileName = iterator.next();

                 mFile = request.getFile(uploadFileName);

            

                 orgFileName = mFile.getOriginalFilename();

                 logger.info(orgFileName);

            

                 if(orgFileName != null && orgFileName.length() != 0) { //sysFileName 생성

                

                   SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMDDHHmmss-" + fileLoop);

                   Calendar calendar = Calendar.getInstance();

                   sysFileName = simpleDateFormat.format(calendar.getTime()); //sysFileName: 날짜-fileLoop번호

                

                

                    try {

                        logger.info("try 진입");

                        mFile.transferTo(new File(dir + File.separator + sysFileName)); // C:/Upload/testfile/sysFileName

                        list.add("원본파일명: " + orgFileName + ", 시스템파일명: " + sysFileName);

                        list.add("파일크기: " + mFile.getSize() + ", 파일형식: " + mFile.getContentType() );

                    

                    }catch(Exception e){

                         list.add("오류: 파일 업로드 중 에러발생!!!");

                    }

                

                }//if

            

            }//while

        

            model.addAttribute("list", list);

return "/board/uploadResult";

}


(중략)


파일명: BoardController.java


[첨부(Attachments)]

BoardController.zip




9. View - board/insert.jsp


사용자 화면에 관한 것이다.


그림 18. /board/insert 페이지


미리 살펴보는 /board/insert 페이지에 대한 것이다.

파일 업로드 영역에 관한 핵심은 아래의 그림과 같다.



그림 19. views/board/insert.jsp



<!-- 파일 업로드 영역 -->

<h3>파일 업로드</h3>

<form method="POST" action="uploadResult" enctype="multipart/form-data">

<table style="width:900px; height:70px;">

<tr>

<td style="width:10%">아이디(UserID)</td>

<td style="width:90%">

<input type="text" name="id" class="login_id">

</td>

</tr>

<tr>

<td>

비밀번호(Password)

</td>

<td>

<input type="password" name="passwd" class="login_pwd">

</td>

</tr>

<tr>

<td colspan="2">

<input type="file" name="uploadFile" multiple>

</td>

</tr>

<tr>

<td colspan="2">

<input type="submit" value="로그인">

</td>

</tr>

</table>

</form>


파일명: insert.jsp


[첨부(Attachments)]

insert.zip



10. View - board/uploadResult.jsp


uploadResult 페이지에 대한 것이다.

앞서 Controller에서 정의된 것을 출력하는 페이지를 가리킨다.



그림 20. /board/uploadResult 페이지


소스코드는 다음과 같다.

c태그를 간단하게 if, else문도 적용시켜보았으니 참고해보면, 좋을 듯 싶다.


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>업로드 - 결과</title>

</head>

<body>


<!-- 업로드 결과 (출력) -->

<c:set var="i" value="1" />

<c:set var="num" value="1" />


<table style="width:700px; border:1px;">

<c:forEach items="${list}" var="list">

<c:choose>

<c:when test="${i == 1}">

<tr>

<td colspan="2" style="background-color:#e2e2e2;">

<c:out value="${num}" />

</td>

</tr>

</c:when>

</c:choose>

<c:choose>

<c:when test="${i <= 3}">

<tr>

<td><c:out value="${i}" /></td>

<td>${list}</td>

<c:set var="i" value="${i + 1}" />

</tr>

</c:when>

<c:otherwise>

<c:set var="i" value="1" />

<c:set var="num" value="${num + 1}" />

</c:otherwise>

</c:choose>

</c:forEach>

</table>

</body>

</html>


* 파일명: uploadResult.jsp


[첨부(Attachments)]

uploadResult.zip



11. 파일 업로드 결과 - 실제 업로드된 모습



그림 21. 파일 업로드 모습 (2020-09-24)



12. 맺음글(Conclusion)


파일 업로드 방법에 대해서 살펴보았다.



* 참고자료(References)


1. Maven Repository: commons-fileupload » commons-fileupload » 1.4, https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload/1.4, Accessed by 2020-09-24, Last Modified 2018-12-24.

2. Maven Repository: commons-io » commons-io » 2.8.0, https://mvnrepository.com/artifact/commons-io/commons-io/2.8.0, Accessed by 2020-09-24, Last Modified 2020-09-09.

3. web.xml 서블릿 버전별 DTD, https://antop.tistory.com/entry/webxml-%EC%84%9C%EB%B8%94%EB%A6%BF-%EB%B2%84%EC%A0%84%EB%B3%84-DTD#footnote_link_145_1, Accessed by 2020-09-24, Last Modified 2013-03-03.


반응형

+ Recent posts