파일업로드 이해하기
우선 파일업로드 관련 DB테이블을 하나 만들어 준다.
board_type는 notice라고주고
board_id는 파일이 업로드 진행된 게시판 번호,
file_num은 시퀀스로 증가하는 파일 번호,
file_name은 원본파일명
saved_file_name은 temp파일명
file_size는 파일의 크기이다.
우리가 파일 업로드를 하기 위해서 구해야 하는것은 이렇게 총 3가지가 있다.
파일을 올리면 웹서버에 저장이 되게 되는데 저장에 문제가 없다면
- notice_info에 등록
- 등록한 sepuence 조회
- board_attach등록
- 웹 서버에 파일 저장하기
첨부파일 나오게 하기 위해서는 input타입을 file로 해야한다.
file 이라는 이름으로 controller로 전달
그리고 form은 입구가 좁기 때문에 확장해주지 않으면 파일이 지나갈 수 없게 된다.
form에서 encType=”multipart/form-data”를 해줌으로써 파일이 지나갈 수 있도록 통로를 꼭 넓혀주도록 하자
우선 파일업로드를 하기위해서 Resolver가 필요하다.
servlet-context에서 multipartResolver bean을 추가해준다.
pom.xml에서도 파일업로드 디펜던시가 있는지 확인하기
jsp에서 게시글 등록할 때 파일업로드도 같이 진행이 되는데
게시글 등록할 때 게시글에 대한 정보는 dto에 담겨있지만 업로드 한 파일은 어디서 담겨있는지 알 수 없다.
MultipartHttpServletRequest 인터페이스는 스프링이 제공하는 인터페이스로써, Multipart요청이 들어올 때 내부적으로 원본 HttpServletRequest대신 사용되는 인터페이스이다.
MultipartHttpServletRequest를 사용해서 getFile메소드를 통해 List형태로 받을 수 있다.
req에 담겨져 있는 파일을 mr에 담아주고 mr.getFile을 통해서 파일을 가져올 수 있다.
이렇게 가져온 파일을 웹서버에 저장을 해야한다.
그렇게 하기 위해서는 파일이 저장될 실제 경로가 필요하다.
path라는 변수에 세션에서 getServletContext().getRealPath을 통해서 경로를 가져온다.
경로를 출력해보면 해당 경로가 나오는데 따라 들어가보면 경로가 존재하지 않을것이다.
따라가보면 폴더가 존재하지 않는다.
그렇다면 우리는 어떻게 폴더를 생성해줄수 있을까?
직접 새 폴더 생성은 옳지 않다,
해당 폴더가 존재하지 않으면 자동으로 만들어 줄 수 있게끔 해주어야 한다.
해당 path(경로)로 들어가는데 존재하지 않는다면 mkdirs를 통해서 디텍토리를 자동으로 생성하게 할 수 있다.
파일의 경로를 saveDir에 담아주고 만약 해당 경로에 파일이 존재하지 않는다면 mkdir()과 mkdirs()를 통해서 디텍토리를 생성한다.
여기서 mkdirs()를 많이 사용한다.
이유는
이렇게 해주게 되면 경로에 파일이 자동으로 생성이 된다.
여기서 이제 파일 가져와서 파일의 original파일명을 name에 저장을 하고
destination에 temp파일명을 저장해준다.
file에 temp파일명을 만드는데 맨 앞에 F_를 붙혀주고 System.currentTimeMillis()을 통해서 파일명이 겹치지 않게 복잡한 숫자와 name에서 subString으로 .뒤에서 붙어 잘라준 확장자명을 다시 붙혀준다.
출력을 하게되면 이러한 형식으로 파일명이 만들어진다.
long size = file.getSize(); 를 통해서 파일의 크기를 가져올 수 있다.
위와 같은 과정을 통해서 temp파일명을 가지고 파일을 경로에 저장하게 되는데 사진에 대한 정보는 없는채로 이름만 저장이 되게 된다.
temp파일명으로 된 파일에 원본 사진 데이터를 입히는 작업을 해야한다.
FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(destination));
위와같은 작업을 통해서 file의 데이터를 copy해서 temp파일명으로 된 파일에다가 입히는 작업을 진행해준다.
이렇게 되면 db에 넣을때 필요한 준비물들이 다 준비가 되게 된다.
우선 파일업로드시 insert 쿼리문을 작성한다.
해당 쿼리문을 통해서 파일 업로드가 진행이 되고 성공적으로 업로드가 되었다면 1
실패했다면 0이라는 값을 반환할것이다.
mapper과 DAO에서 메소드 작성해주고
게시글 작성하는 service에서 Map형식으로 한번에 넘겨주기 위해서 param 변수 생성
board_id라는 key값으로 dto의 게시글 넘버,
file_name라는 key값으로 original파일명,
saved_file_name라는 key값으로 temp파일명,
file_size라는 key값으로 파일의 크기를 넣어서 넘겨준다.
이 param을 통째로 db로 넘겨주면 된다.
그렇게 되면 쿼리문에서 정상적으로 실행이 되었다면 파일이 등록되게 될것이다.
여기서 문제점이 있을 수 있다.
게시글 작성이 되지 않았을때이다.
게시글 작성이 되지 않았을때 파일이 업로드되면 안될것이다.
dto에 전달하는 과정에서 성공적으로 전달이 되었다면 정상적으로 값을 가져오기 때문에 1을 반환하고 그렇지 않다면 dto에 전달하는 과정에서 문제가 생겼기 때문에 게시글이 정상적으로 작성이 되지 않았을 것이다.
그렇기 때문에 롤백을 통해서 파일을 삭제해주어야 할것이다.
'Spring' 카테고리의 다른 글
DTO, DAO, VO (0) | 2022.04.24 |
---|---|
Get과 Post (0) | 2022.04.24 |
비동기통신과 동기통신 (0) | 2022.04.24 |
Ajax와 xmlhttprequest (0) | 2022.04.24 |
페이징처리 (0) | 2022.04.24 |