본문 바로가기

Programming/SPRING

Spring Multipart를 이용한 이미지 업로드

출처 : 


1. fileTest.jsp 생성


JSP를 다음과 같이 생성하고 FORM 태그를 사용하여 다음과 같이 작성하자.

가장 중요한건 multipart/form-data를 설정해 줘야 한다는것.

주석에 순서대로 설명을 달아놓았다.


해당 소스는 "제출" 버튼을 누르면 submit동작에 의해 /fileUpload로 매핑되어져 있는

Contorller를 호출한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<%@ page contentType = "text/html;charset=utf-8" %>
<html>
<head>
    <title>Home</title>
</head>
<body>
    <!-- 
1. 전송하고자 하는 입력 폼을 <form>과 </form>사이에 위치해놓는다. 
2. action 값은 데이터를 전송받아서 처리할 Controller url로 설정한다.
3. method를 반드시 post로 설정해준다. get으로 설정시 parameter들이 url에 따라간다.
4. enctype을 multipart/form-data로 설정한다.
5. <form>과 </form>사이에 input type submit버튼을 위치시킨다.
-->
    <form action="./fileUpload" id="fileUpload" name="fileUpload" method="post" enctype="multipart/form-data">
        이름 : <input type="text" name="name" id="cmd" value="namevla"><br>
        파일 : <input type="file" name="file"><br> <input
            type="submit" name="업로드" value="제출"><br>
    </form>
</body>
</html>
 
cs


2. action Url에 fileupload 메소드 작성


action url이 매칭되는 /fileUpload 에 file upload 소스를 작성한다!

multipart/form-data는 서버에서 MultipartHttpServletRequest 로 받아야 한다.


아래 소스는 저장하고자 하는 물리적인 경로에 업로드한 파일의 파일명을 암호화 한뒤 저장하는 소스이다.

(c://aaa 처럼... 저장 하고 싶은 경로를 적어준다.)


DB에 저장하고 싶다면 보통 파일 Data만을 관리하는 TABLE을 생성한 뒤

파일명, 파일경로, 파일사이즈 MultipartHttpServletRequest에서 핸들링하여 추출한 뒤, service와 dao를 거쳐 INSERT 해 주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
 
/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
    
    @RequestMapping(value = "/fileUpload", method = RequestMethod.POST)
    public Map fileUpload(HttpServletRequest req, HttpServletResponse rep) { 
        //파일이 저장될 path 설정 
        // String path = req.getSession().getServletContext().getRealPath("") + "\\resources";    // 웹프로젝트 경로 위치
        String path = req.getSession().getServletContext().getRealPath("/resources/");
        
        System.out.println("path : " + path);
        
        Map returnObject = new HashMap(); 
        try { 
            // MultipartHttpServletRequest 생성 
            MultipartHttpServletRequest mhsr = (MultipartHttpServletRequest) req; 
            Iterator iter = mhsr.getFileNames(); 
            MultipartFile mfile = null
            String fieldName = ""
            List resultList = new ArrayList(); 
            
            // 디레토리가 없다면 생성 
            File dir = new File(path); 
            if (!dir.isDirectory()) { 
                dir.mkdirs(); 
            } 
            
            // 값이 나올때까지 
            while (iter.hasNext()) { 
                fieldName = (String) iter.next(); // 내용을 가져와서 
                mfile = mhsr.getFile(fieldName); 
                String origName; 
                origName = new String(mfile.getOriginalFilename().getBytes("8859_1"), "UTF-8"); //한글꺠짐 방지 
                
                System.out.println("origName: " + origName);
                // 파일명이 없다면 
                if ("".equals(origName)) {
                    continue
                } 
                
                // 파일 명 변경(uuid로 암호화) 
//                String ext = origName.substring(origName.lastIndexOf('.')); // 확장자 
//                String saveFileName = getUuid() + ext;
                String saveFileName = origName;
                
                System.out.println("saveFileName : " + saveFileName);
                
                // 설정한 path에 파일저장 
                File serverFile = new File(path + File.separator + saveFileName);
                mfile.transferTo(serverFile);
                
                Map file = new HashMap();
                file.put("origName", origName); file.put("sfile", serverFile);
                resultList.add(file);
            }
            
            returnObject.put("files", resultList); 
            returnObject.put("params", mhsr.getParameterMap()); 
            } catch (UnsupportedEncodingException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            }catch (IllegalStateException e) { // TODO Auto-generated catch block 
                e.printStackTrace();
            } catch (IOException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
            return null;
    }
    
    //uuid생성
    public static String getUuid() { 
        return UUID.randomUUID().toString().replaceAll("-""");
    }
}
cs


이렇게 작성하고 룰루랄라 실행을 해보면 

다음과 같은 에러를 뿜게 될 것이다.

왜냐하면 설정을 빠뜨렸기 떄문이다.

Spring에서 file upload를 사용하기 위해서는 설정파일에 Multipart에 관련된 설정을 꼭 해줘야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
java.lang.ClassCastException: org.apache.catalina.connector.RequestFacade cannot be cast to org.springframework.web.multipart.MultipartHttpServletRequest
 com.example.sts.TestController.fileUpload(TestController.java:31)
 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 java.lang.reflect.Method.invoke(Method.java:483)
 org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
cs


3. servelet-context.xml 에 multipartResolver 설정 추가



*** Spring에서는 encType="multipart/form-data" 을 사용하기 위해 CommonsMultipartResolver 를 꼭 설정해줘야 한다.


COmmonsMultipartResolver는 스프링에서 파일업로드 기능을 구현해놓은 클래스이다. 해당 클래스가 file upload를 처리해 주며, maxUploadSize는 이름만 봐도 추측이 가능하다. 바로 서버에 업로드 할 수 있는 첨부파일의 최대 크기를 의미하는데 단위는 byte이다. 알맞게 설정해 주면 된다.

1
2
3
4
<beans:bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <beans:property name="maxUploadSize" value="10000000" />
</beans:bean>
cs


또한, 해당 크기 이상의 파일을 첨부하면 자동으로 Spring에서 에러를 떨궈주게 된다. 


4. pom.xml 에 dependency 추가


COmmonsMultipartResolver를 추가했음에도 file upload에 다음과 같은 에러가 난다면..............

1
2
3
4
5
6
7
8
9
10
java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory
 java.lang.Class.getDeclaredConstructors0(Native Method) 
 java.lang.Class.privateGetDeclaredConstructors(Class.java:2663
 java.lang.Class.getDeclaredConstructors(Class.java:2012)
 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:229)
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:962)
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:935)
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
 
cs

pom.xml에 dependency를 추가해 줬나 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
<!-- File Upload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.4</version>
</dependency>
cs


5. 결과확인


파일을 업로드 하게 되면...................................