Spring 에서 MultipartFile 인터페이스를 지원해준다.
파일저장을 도와주고 Temporary storage 에 잠시 있다 요청처리가 끝나면 지워지게 된다.
메소드 소개(getName, getOriginalrFilename, isEmpty, getSize, getBytes, transforTo)
여기서 가장 중요한 것은 transferTo 메소드이다. 메소드에 설명을 간단히 보면 파일을 저장할 수 있고 대상 파일이 이미 존재하는 경우 기존에 존재하는 걸 삭제한다.
1.프론트 부분
Html 코드에 multiple을 추가해준다.
여기서 RestController에 요청을 보내야 하는데 어떻게 보낼까?
Axios를 사용해서 RestController에 요청을 보낸다.
하나씩 살펴보자
async
function 앞에 async를 붙일 경우 함수는 항상 Promise를 반환하게 된다. 여기서 Promise는 비동기 작업의 단위이다. 비동기 작업이기에 이 작업이 언제 끝날지 알 수 없다. 그렇기에 이 함수가 실행된 이후 성공하거나 실패하는 순간에 처리를 해주어야 한다. Promise가 끝나고 난 다음의 동작을 설정할 수 있고 그 설정은 then 과 catch로 설정할 수 있다. (async 함수의 리턴 값은 Promise이다.)
await
await은 async 함수 내에서만 쓸 수 있다. await은 Promise 를 기다리기 위해 사용되고 Promise가 fulfill되거나 reject 될때까지 async 함수의 실행을 일시 정지하고, Promise가 fullfill되면 async 함수를 일시 정지한 부분부터 실행한다. 이때 await 문의 반환값은 Promise에서 fulfill(달성한)된 값이 된다. 여기서 fullfilled는 이행상태로서 연산이 성공저긍로 완료된 상태이고 rejected는 거부 상태로서 연산이 실패한 상태이다.
출처 - https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/await
axios
웹 통신 기능을 제공하는 라이브러리 중 하나이다.
axios는 요청을할때 config 설정이 가능하다.
- method
method는 요청을 할떄 사용할 요청 메소드이다. (default는 get)
- url
axios 요청에 사용될 서버 url이다.
- headers
헤더 값을 수정해서 보내야 할 경우 headers를 사용하면된다.
- data
Http 요청 body에 실어서 보낼 데이터를 의미한다.
- params
params는 HTTP 요청에 붙일 URL 파라미터를 의미한다. (쿼리스트링 ?key=value 를 의미)
-timeout
timeout은 Http 요청을 보내고 응답을 받기까지의 제한 시간을 설정하는 속성이다.
-responseType
responseType은 서버로부터 어떠한 데이터 형식으로 응답받을지 지정할 수 있다. (ex - responseType: 'json')
이미지를 받기위해 Modal을 사용한다.
Modal 창에서 업로드 버튼을 클릭시 위에 설명한 비동기처리 함수를 실행시켜야한다.
formData
FormData() 생성자는 새로운 FormData 객체를 만든다. form 요소로 지정된 경우 FormData 객체는 form의 현재 key/value들로 값들이 채워지고(name:value) 따로 채우려면 append()를 사용한다.
위에서는 input 태그에 여러개에 파일이 들어올 수 있다. 그러기에 파일이 들어온만큼 for문을 돌려서 file이 있는만큼 append()를 FormData에 추가한다.
then,catch
위에서 말한것처럼 uploadToServer는 async로 비동기함수로 만들었다. 그렇기에 Promise를 반환한다. 그래서 함수가 성공적으로 실행되었을떄 then을통해 데이터를 처리할 수 있고 만약 에러가 난다면 catch로 잡을 수 있다.
result는 위에 uploadToServer 함수에서 반환하던 response.data 값이 넘어온다.
물론 여기서도 몇개가 넘어올지 모르기에 for 문을 돌려준다. showUploadFile() 함수는
Modal을 통해 이미지를 저장하면 이미지 전체가 하나씩 보여질 것이다.
2. RestController
위에 코드를 통해 모달창을 열게 되면
이 모달창을 통해 RestController에 요청을 넣는다.
consumes는 클라이언트가 서버에게 보내는 데이터 타입을 명시하는 속성이다. 위에 input 타입에서 multipart/form-data로 타입을 정해서 요청을 넣었기에 consumes 속성값을 지정해서 넣어면된다.
여기서 받는 Body로 받는 데이터타입은 FileDTO이다.
MultipartFile 타입은 스프링에서 제공하는 것이고 HTTP 요청이 multipart 타입을 처리할 수 있다. 이게 여러개일 경우를 대비해서 List타입으로 만들면 좋다. 그렇기에 DTO를 사용
MultipartFile에 있는 메소드들은 위에 다 적혀있다.
업로드한 결과를 보내줄 DTO
Body로 받은 데이터 fileDTO에 MultipartFile이 비었는지를 isEmpty를 통해 확인한다. 그리고나서 리턴해줄 매개변수인 list를 생성한다.
uuid는 각 파일에 식별자를 생성하기 위해 선언하는 것이고 랜덤한 식별자가 각각 생성된다.
originalName은 클라이언트에서 들어온 요청에 파일 이름이다.
Paths.get()은 두개에 파라미터를 합친 Path객체를 생성해준다. uploadPath는 파일을 저장할 위치이고 뒤에 uuid는 각 파일에 식별자 그리고 originalName은 클라이언트에서 요청을 넣은 파일에 이름이다.
image 값은 아래에서 이미지인지 체크하기 위해 일단 false로 둔다.
이제 List객체안에 든 multipartFile을 업로드하려면 transferTo 메소드가 필요하다. transferTo메소드를 통해 업로드를 시키는데 매개변수로는 Path도 가능하고 File도 가능하다. 위에서 만든 Path에 파일을 업로드한다.
그리고 아래 Thumbnailator 는 섬네일을 만들게 도와준다.
파라미터로 File 타입만 받는데 첫번째 파일은 파일로만들 File로 받고 두번쨰 파라미터에는 출력할 파일을 받기에 이름에 s_ 를 추가한 File 객체를 생성했고 그렇게 썸네일로 사용할 이미지가 기존 파일과 같은 경로에 s_가 추가된 형태로 올라가게 될 것이다.
probeContentType을 통해 파일에 콘텐츠 타입을 확인할 수 있다.
만약 이미지 일경우
Content-Type:image/png
Content-Type:image/jpg
이런형태로 나오기에 startWith() 메소드를 통해 이미지인지 확인할 수 있다.
이제 파일을 업로드한 UUID와 fileName을 FileDTO 객체로 만들어서 맨위에 선언한 리스트에 추가한다.
그러고 이 리스트를 반환한다. 밑에 return null은 클라이언트에서 받은 multipart 데이터 타입에 데이터가 없을때 null을 반환한다.
3.파일올리는 결과
UUID와 파일이름이 결합된 이미지와 썸네일로 사용될 s_ + UUID + 파일이름이 결합된 이미지 총 두장이 저장되는 결과를 볼 수 있다.
파일을 출력하는 건 다음 장에서...
'Spring' 카테고리의 다른 글
Spring - Session (0) | 2022.12.26 |
---|---|
Spring - Cookie (0) | 2022.12.23 |
JPA - N+1 (0) | 2022.09.19 |
JPA - @EntitiyGraph, @Transactional Database - NoSession 해결 (0) | 2022.09.15 |
JPA - Querydsl 정의(간단한 검색기능) (0) | 2022.09.03 |