Spring으로 파일 업로드

2016. 12. 28. 17:04Programming/Spring

순서:

1) servlet-context.xml 세팅(MultipartResolver 추가)

2) pom.xml에서 사용할 라이브러리 추가(commons-io & commons-fileupload)

3) Board 빈 객체에 두 칼럼 추가

4) 컨트롤러에서 insert.do 수정

5) BoardAddForm에서 insert 값에 따라 alert 출력

6) 뷰 페이지에서 이미지 출력



1) servlet-context.xml 세팅(MultipartResolver 추가)



<servlet-context.xml>

1
2
3
4
<!-- form에서 데이터 전달 방식이 multipart/data인 경우 아래 resolver 사용 -->
    <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <beans:property name="maxUploadSize" value="10485760" />
    </beans:bean>
cs



2) pom.xml에서 사용할 라이브러리 추가(commons-io & commons-fileupload)


<pom.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
 
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.2</version>
        </dependency>
cs



3) Board 빈 객체에 두 칼럼 추가


<Board.java(빈 객체)>

다음 두 칼럼 추가 + getter/setter

private String filename;

private MultipartFile newfile;



4) 컨트롤러에서 insert.do 수정


<BoardController.java>

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
@RequestMapping(value="/insert.do", method=RequestMethod.POST)
    public String insert(Board board, Model model, HttpServletRequest req, RedirectAttributes rttr){
        logger.info("==================insert.do post start==============");
        int insert = 0;
        int maxNum = 1;
        //spring MultipartFile은 form에서 넘어온 file을 byte type으로 들고 있다. 저장 X
        if (board.getNewfile() != null) {
            MultipartFile file = board.getNewfile();
            // 받아온 파일의 contentType이 image인 경우에만 저장함
            if (file.getContentType().split("/")[0].equals("image")) {
                logger.info("filename:" + file.getOriginalFilename() + "//size:" + file.getSize());
                // 저장할 경로, 확장자
                String saveDirectory = req.getSession().getServletContext().getRealPath("/resources/img");
                String fileExtend = file.getOriginalFilename()
                        .substring(file.getOriginalFilename().lastIndexOf("."+ 1);
                // 저장할 이름
                String newFilename = "board_" + System.currentTimeMillis() + fileExtend;
                board.setFilename(newFilename);
                
                try (FileOutputStream fos = new FileOutputStream(saveDirectory + "//" + newFilename)) {
                    byte fileData[] = file.getBytes();
                    fos.write(fileData);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                
            //contentType이 image가 아닐 경우
            } else {
                insert = -1;
            }
        }
        if (insert != -1) {
            maxNum = dao.selectMaxNum();
            board.setNum(maxNum + 1);
            logger.info(board.toString());
            insert = dao.insertBoard(board);
        }
        //insert 성공/실패 분기
        String url = "insert.do";
        if (insert > 0) {
            url = "detail.do";
            rttr.addAttribute("num", board.getNum());
            rttr.addFlashAttribute("insert",insert);
        } else {
            rttr.addFlashAttribute("insert",insert);
        }
        logger.info("==================insert.do post end==============");
        return "redirect:"+url;
    }
cs



5) BoardAddForm에서 insert 값에 따라 alert 출력 + multipart~ 추가


<BoardAddForm.jsp>

1
2
3
4
5
6
7
8
<script type="text/javascript">
var insert = "${insert}";
if(insert=="0"){
    alert("저장 실패");
}else if(insert=="-1"){
    alert("이미지 파일만 등록 가능합니다.");    
}
</script>

<form action="insert.do" method="post" enctype="multipart/form-data">
cs



6) 뷰 페이지에서 이미지 출력


<BoardDetail.jsp>

1
2
3
4
5
<p>
    <label> img:</label>
    <c:url value="/resources/img/${board.filename}" var="imgUri"/>
    <img alt="빈 이미지 입니다." src="${imgUri}">
</p>
cs



<업로드 기능을 util에 분리할 경우>



<ImgFileUploadUtil.java>

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
public class ImgFileUploadUtil {
    private MultipartFile file;
    private String savePath;
    private String filename; //board_, member_
    private String newFilename; //board_12312313.jpg
    private String extension; //jpg,png
    private boolean newFileFlag = false;
    
    public String getNewFileName(){
        return newFilename;    //새롭게 만들어진 파일 이름을 DB에 저장하기 위해 넘겨준다.
    }
    
    //생성자 역할
    public ImgFileUploadUtil(String savePath, MultipartFile file, String filename){
        this.file=file;
        this.filename=filename;
        this.savePath=savePath;
        this.extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."+ 1);
        this.newFilename = filename+"_"+System.currentTimeMillis()+"."+extension;
    }
    
    public boolean newFile(){
        //File.separator : "//"와 동일
        /*try (FileOutputStream fos = new FileOutputStream(savePath + File.separator + newFileName)) {
            byte fileData[] = file.getBytes();
            fos.write(fileData);
            newFileFlag = true;
        } catch (Exception e) {e.printStackTrace();}*/
        
        //더 간단하게 쓰려면?
        try{
            FileCopyUtils.copy(file.getBytes(), new File(savePath, newFilename));
            newFileFlag = true;
        }catch(Exception e){
            e.printStackTrace();
        }
        return newFileFlag;
    }
}
cs




<BoardController.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                //윗 부분은 동일
// 저장할 경로
                String saveDirectory = req.getSession().getServletContext().getRealPath("/resources/img");
                ImgFileUploadUtil uploadUtil = new ImgFileUploadUtil(saveDirectory, file, "board");
                
//파일 생성( newFile();) -> 빈객체에 파일 정보 넣기
boolean newFileFlag = false;
                newFileFlag = uploadUtil.newFile();
                if(newFileFlag){
                    board.setFilename(uploadUtil.getNewFileName());

                //파일 저장 실패
                }else{
                    insert = -2;
                }
            //contentType이 image가 아닐 경우
            } else {
                insert = -1;
            }
cs



<MemberController.java>

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
@RequestMapping(value="/update.do", method=RequestMethod.POST)
    public String update(Member mem, @RequestParam("newfile") MultipartFile newfile, HttpServletRequest req, RedirectAttributes rttr){
        int update = 0;
        MemberAlbumVo albumVo = new MemberAlbumVo();
        boolean newFileFlag = false;
        ImgFileUploadUtil uploadUtil = null;
        String saveDirectory = req.getSession().getServletContext().getRealPath("/resources/img");
        
        if(newfile.getOriginalFilename()!=null){
            if (newfile.getContentType().split("/")[0].equals("image")) {
                uploadUtil = new ImgFileUploadUtil(saveDirectory, newfile, "member");
                newFileFlag = uploadUtil.newFile(); //새 파일 생성
                
                //bean 객체에 파일 정보 넣기
                if (newFileFlag) {
                    albumVo.setPhoto(uploadUtil.getNewFileName());
                    albumVo.setThumbnail(uploadUtil.makeThumbnail(80));
                    albumVo.setMem_num(mem.getNum());
                // 파일 저장 실패
                } else {
                    update = -2;
                }
            // contentType이 image가 아닐 경우
            } else {
                update = -1;
            }
        }
        
        //update 직전시
        if (update > -1) {
            try {
                //업데이트 대신 delete 후 새로 insert
                dao.updateMember(mem, albumVo); 
                update = 1;
            } catch (Exception e) {
                logger.debug(e.getMessage());
            }
        }
        //update 성공시
        if(update > 0){
            if(mem.getPhoto()!=null){
                logger.info("기존photo삭제:"+new File(saveDirectory,mem.getPhoto()).delete());
            }
            if(mem.getThumbnail()!=null){
                logger.info("기존thumbnail삭제:"+new File(saveDirectory,mem.getThumbnail()).delete());
            }
        //update 실패시
        }else{
            if(newFileFlag){
                logger.info("새photo삭제:"+uploadUtil.newFileDelete());
                logger.info("새thumbnail삭제:"+uploadUtil.thumbnailDelete());
            }
            rttr.addAttribute("num", mem.getNum());
            rttr.addAttribute("update", update);            
        }
            
        String url = (update > 0) ? "list.do" : "update.do";
        return "redirect:" + url;
    }
cs


'Programming > Spring' 카테고리의 다른 글

썸네일(Thumbnail) 만들기  (0) 2017.01.02
Spring으로 파일 수정, 게시글+댓글 삭제  (0) 2016.12.30
AJAX로 인터셉터 구현하기  (0) 2016.12.27
AJAX로 페이징 구현하기  (0) 2016.12.27
AJAX로 댓글 기능 구현  (0) 2016.12.23