스프링 프레임워크의 내장 객체인 CommonsMultipartResolver 를 이용한 파일 업로드 방식이다.


1. pom.xml 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
    <!-- MultipartHttpServletRequset -->
    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.0.1</version>
        </dependency>
 
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.2</version>
        </dependency>
    </dependencies>
 
</project>
cs

pom.xml 파일에서

ㄱ. commons-io.jar

ㄴ. commons-fileupload.jar

두 가지 .jar를 추가한다.



2. context.xml 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- MultipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="100000000"/>
        <property name="maxInMemorySize" value="100000000"/>
    </bean>
 
</beans>
cs

context.xml에서 CommonsMultipartResolver 객체를 추가한다.


CommonsMultipartResolver는 스프링 프레임워크에 내장되어 있는 MultipartResolver 이다.


* maxUploadSize : 한 번에 최대 올릴 수 있는 파일 사이즈

  maxInMemorySize : 해당 경로에 최대로 저장할 수 있는 파일 사이즈



3. form 파일 업로드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
    <title>title</title>
</head>
<body>
 
    <!-- form enctype="multipart/form-data" 을 꼭 적어줘야 함 -->
    <form class="form-horizontal" method="post" action="<c:url value='/re/add'/>" enctype="multipart/form-data">
        <!-- input type="file" 이라고 꼭 저어줘야 함 -->
        <input type="file" class="form-control1" id="uploadFile" name="uploadFile" style="border:0px solid black;"/>
        
        <button type="submit" class="btn btn-default">등록</button>
        <button type="reset" class="btn btn-default">취소</button>
    </form>
 
</body>
</html>
cs

form enctype="multipart/form-data"라고 꼭 적어줘야 한다. 그렇지 않으면 form이 전송되지 않는다.

마찬가지로 전송할 파일 타입도 file이라고 적어줘야 한다.



4. MultipartResolver 클래스 작성

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
package com.cafe24.smart.util;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.view.AbstractView;
 
import com.cafe24.smart.approve.domain.Draft;
import com.cafe24.smart.reward.domain.Reward;
 
// @Component > @Service
//              : 스프링 프레임워크가 관리하는 컴포넌트의 일반적 타입 
//              : 개발자가 직접 조작이 가능한 클래스의 경우 해당 어노테이션을 붙임
//              : ( <=> @Bean : 개발자가 조작이 불가능한 외부 라이브러리를 Bean으로 등록시 사용)
@Component
public class UtilFile {
    String fileName = "";
    
//  프로젝트 내 지정된 경로에 파일을 저장하는 메소드
//  DB에는 업로드된 전체 경로명으로만 지정되기 때문에(업로드한 파일 자체는 경로에 저장됨)
//  fileUpload() 메소드에서 전체 경로를 리턴받아 DB에 경로 그대로 저장   
    public String fileUpload(MultipartHttpServletRequest request,
                                        MultipartFile uploadFile, Object obj) {
        String path = "";
        String fileName = "";
        
        OutputStream out = null;
        PrintWriter printWriter = null;
        
        try {
            fileName = uploadFile.getOriginalFilename();
            byte[] bytes = uploadFile.getBytes();
            path = getSaveLocation(request, obj);
            
            System.out.println("UtilFile fileUpload fileName : " + fileName);
            System.out.println("UtilFile fileUpload uploadPath : " + path);
            
            File file = new File(path);
            
//          파일명이 중복으로 존재할 경우
            if (fileName != null && !fileName.equals("")) {
                if (file.exists()) {
//                    파일명 앞에 업로드 시간 초단위로 붙여 파일명 중복을 방지
                    fileName = System.currentTimeMillis() + "_" + fileName;
                    
                    file = new File(path + fileName);
                }
            }
            
            System.out.println("UtilFile fileUpload final fileName : " + fileName);
            System.out.println("UtilFile fileUpload file : " + file);
            
            out = new FileOutputStream(file);
            
            System.out.println("UtilFile fileUpload out : " + out);
            
            out.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (printWriter != null) {
                    printWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        return path + fileName;
    }
    
//  업로드 파일 저장 경로 얻는 메소드
//  업로드한 파일의 경로가 도메인 별로 달라야 했기 때문에 도메인의 형을 비교하여 파일 저장 정로를 다르게 지정함
    private String getSaveLocation(MultipartHttpServletRequest request, Object obj) {
        
        String uploadPath = request.getSession().getServletContext().getRealPath("/");
        String attachPath = "resources/files/";
        
//      Reward인 경우
        if (obj instanceof Reward) {
            attachPath += "reward/";
//      Approval인 경우
        } else if(obj instanceof Draft) {
            attachPath += "approval/";
//      Document인 경우            
        } else {
            attachPath += "document/";
        }
        
        System.out.println("UtilFile getSaveLocation path : " + uploadPath + attachPath);
        
        return uploadPath + attachPath;
    }
}
cs

시간이 촉박했기 때문에 파일의 경로를 암호화하는 UUID 객체는 사용하지 않았다.


getSaveLocation() 메소드에서 저장될 경로를 지정할 때 해당 프로젝트의 경로를 변수 uploadPath로 값 복사하였는데

로컬에서는 (본인의 컴퓨터) 에서는 아무리 해당 경로를 찾아봐도 업로드 했던 파일이 나오지 않는다.

그러나 cafe24 같은 서버에 프로젝트를 호스팅 하면 지정 경로로 업로드가 잘 되니 걱정하지 않아도 된다.



5. form에서 보낸 파일 업로드

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
@Controller
public class RewardController {
//  파일을 업로드하는 컨트롤러 클래스 메소드
    @RequestMapping(value = "re/add", method = RequestMethod.POST)
//  인자로 MulfiPartFile 객체, MultipartHttpServletRequest 객체, 업로드 하려는 도메인 클래스를 받는다
    public String reAddProCtrl(@RequestParam("uploadFile") MultipartFile uploadFile,
                                    MultipartHttpServletRequest request, Reward reward) {
        
        System.out.println("RewardController reAddProCtrl uploadFile : " + uploadFile);
        System.out.println("RewardController reAddProCtrl reward : " + reward);
        
//      UtilFile 객체 생성
        UtilFile utilFile = new UtilFile();
        
//      파일 업로드 결과값을 path로 받아온다(이미 fileUpload() 메소드에서 해당 경로에 업로드는 끝났음)
        String uploadPath = utilFile.fileUpload(request, uploadFile, reward);
        
//      해당 경로만 받아 db에 저장
        int n = rewardService.reAddServ(uploadPath, reward);
        
        System.out.println("RewardController reAddProCtrl n : " + n);
        System.out.println("RewardController reAddProCtrl uploadPath : " + uploadPath);
        
        return "redirect:listAll";
    }
}
cs

이로서 업로드가 끝난다.

'BackEnd > Java' 카테고리의 다른 글

LinkedHashMap  (0) 2017.06.29
RSA 암호화 구현  (0) 2017.03.14
가변인수 (Java 5.0 이상)  (0) 2017.02.13
Java :: 열거형 (Enumeration) (Java 5.0 이상)  (0) 2017.02.13
초기화 블록 (Initialization block)  (0) 2017.02.13

+ Recent posts