본문 바로가기
Spring 프레임워크/이론

Spring 프레임워크 MultipartFile 인터페이스

by Hwanii_ 2023. 8. 17.
728x90

1. 

MultipartFile ?

 

MultipartFile은 Spring 프레임워크 에서 제공하는 인터페이스 이다.

HTTP 요청으로 전송된 파일 데이터를 처리하기 위한 방법을 추상화 했다.

주로, 파일 업로드 기능을 구현할 때 사용 된다.

 

Spring의 MultipartResolver 을 통해, 멀티파트 요청을 해석하고,

파일 데이터를 MultipartFile 객체로 변환하여 컨트롤러에 전달 한다.

 

Spring 에서 MultipartFile파일 업로드를 처리하는 매우 유용한 기능을 한다.

그래서,

업로드를 쉽게 구현 할 수 있고,

업로드된 파일의 정보를 쉽게 추출하고 처리 할 수 있다.

 

 

2.

MultipartFile 인터페이스의 메서드.

 

String getName()

업로드된 파일의 파라미터 이름을 반환 한다.

 

String getOriginalFilename()

클라이언트 (사용자) 가 업로드한 파일의 원래 이름을 반환 한다.

 

String getContentType()

업로드된 파일의 컨텐츠 타입을 반환 한다.

 

boolean isEmpty()

업로드된 파일이 비어있는지 여부를 반환 한다.

 

long getSize()

업로드된 파일의 크기를 반환 한다.

 

byte[] getBytes()

업로드된 파일의 내용을 바이트 배열로 반환 한다.

 

InputStream getInputStream()

업로드된 파일의 내용을 읽을 수 있는 'InputStream' 을 반환 한다.

 

void transferTo(File dest)

업로드된 파일을 주어진 파일 경로에 저장 한다.

 

3.

MultipartFile 인터페이스를 사용 하기 위해서는,

사용하려고 하는 프로젝트에 .jar 파일을 추가 해야 한다.

>>

pom.xml 파일에 라이브러리를 추가 한다.

 

<!-- 파일 업로드 -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>

 

 

 

잘 추가 되었으면, 외부 라이브러리에 fileupload 가 추가된 모습을 확인 할 수 있다.

 

 4.

사용자 (클라이언트) 가 업로드한 파일은, Controller 가 받게 되는데,

이때,

이 업로드한 파일을 받는 방법은 다양 하지만,

 

MultipartFile 인터페이스를 사용해보자.

왜 ?

파일 업로드를 처리할 때, 쉽고, 간단하고, 유용한 여러가지 메서드들이 있으니까 ~

 

게시판의 기능이 있다고 가정해보자.

사용자가 게시글을 작성 할 때, 파일을 업로드 할것이다.

 

따라서,

Command 객체인 BoardVO 클래스 내부에 MultipartFile 인터페이스를 멤버로 선언 한다.

 

MultipartFile 를 멤버변수로 선언했으니, 당연히, getter와 setter도 만들어 준다.

 

 

이때,

멤버변수로 작성된 MultipartFile 은 일반 자료형인 (원시타입인) int, double, .. 등이 아니라,

다른 자료형의 객체를 멤버 변수로 선언한것이 특이점 이라고 볼 수 있다.

 

사실, String도 엄밀하게 보면, 위와 동일한 개념이긴 하다.

 

암튼,

Command 객체인,

BoardVO 클래스 내부에 MultipartFile 자료형의 참조변수가 변수로 선언 되었으니,

해당 변수를 사용 할 수 있게 되었다.

 

흐름은 아래와 같다.

>>

사용자가 fileUpload 라는 파라미터명으로 특정한 파일을 업로드 하고,

특정한 .do 요청을 보내면,

Controller가 특정한 .do 요청을 매핑해서 받고,

Command 객체인 BoardVO를 객체화 (new) 해주고,

request 내장 객체로 부터 값을 추출 한다.

 

이때,

객체를 멤버변수로 사용하는 경우,

해당 객체에 맞는 Resolver 객체가 (주체) 필요 하다.

>> MultipartResolver

 

이때,

다양한 종류의 Resolver 들은 DispatcherServlet의 멤버변수 라서,

DispatcherServlet-servlet.xml 에서 의존 주입 설정을 해줘야 한다. (객체화)

 

암튼,

Command 객체가 자동으로 setter 까지 호출 해서, 파라미터명이 맞는 데이터를 알아서 set 하고,

bVO 객체에 fileUpload가 자동으로 set 될테니까,

getter을 통해서 Controller로 보내진 set된 파일을 사용 할 수 있게 된다.

이때,

MultipartFile 인터페이스가 제공하는 유용한 메서드를 사용해서,

원하는 기능을 쉽고 간단하게 사용 할 수 있게 되는 개념 이다.

 

사용자가 업로드한 파일을 fileUpload 라는 변수에 저장해서 사용 하기.

 

5.

MultipartResolver

 

Spring의 MultipartResolver 을 통해, 멀티파트 요청을 해석하고,

파일 데이터를 MultipartFile 객체로 변환하여 컨트롤러에 전달 한다.

 

MultipartResolverDispatcherServlet-servlet.xml 에서 의존 주입 설정을 해줘야 한다.

 

<bean id = "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- value = "-1" 이면 업로드 사이즈를 무제한 으로 하겠다는 의미 이다. -->
            <property name = "maxUploadSize" value = "-1" />
</bean>

 

 

<property> 태그를 사용한 모습도 확인 할 수 있다.

 

6. 

위와 같은 설정이 모두 끝났으니,  MultipartFile 를 사용해보자.

 

InsertBoardController.java 클래스 내부의 코드 이다.

 

 

MultipartFile 이 제공하는 메서드를 사용한 모습을 확인 할 수 있다.

 

만약 파일이 비어있지 않으면,

사용자가 업로드한 파일의 오리지날 이름을 String fileName에 저장한다.

 

파일명이 무엇인지 로그가 작성 되어 있고,

 

주어진 파일을 해당 경로에 복사 하는 기능을 하는 transferTo() 메서드를 확인 할 수 있다.

 

 

위의 이미지와 같이, 업로드한 파일이 images 폴더에 복사되는 모습을 확인 할 수 있다.

 

transferTo() 메서드를 사용할까 ?

 

예시)

갤러리 / 사진

스노우 어플 전용 폴더가 생성 된다.

또는

인스타그램 전용 폴더가 생성 된다.

 

이때, 업로드 하거나, .. 을 하면, 전용 폴더에 파일이 저장되는 모습을 확인 할 수 있는데,

 

이는, 관리가 용이 하기 때문에 이런식으로 프로그래밍이 되어있다고 생각 할 수 있다.

 

파일명 중복을 우려해서 어플리케이션 전용 폴더를 별도로 생성 하고,

생성된 별도의 폴더에 파일을 복사 하고, 저장 하여 관리 되는 방식 이다.

 

7.

DB에 저장하기.

 

사용자가 업로드한 파일을 (이미지) DB에 저장 할 수는 없을까 ?

 

파일 자체는 객체 이기 때문에, DB에 직접적으로 파일 자체를 저장 할 수는 없다.

 

대신에 !

파일명을 기억할 칼럼을 생성 하고, 파일명을 칼럼의 행에 저장하여, 

해당하는 행의 데이터 == 파일명 을 사용해서,

사용자가 업로드한 파일을 (이미지) 사용 할 수 있겠다.

 

Board 테이블 확인 하기.

 

 

현재, Board 테이블의 칼럼은 5개로,

BID 는 Board 테이블의 PK == 식별자

TITLE 은 게시글 제목,

CONTENT 는 게시글 내용,

WRITER 은 게시글 작성자,

CNT 는 게시글 조회수 를 의미하는 칼럼 이다.

 

여기에, 업로드한 파일명을 기억 할 수 있게 칼럼을 새롭게 생성 한다.

 

 

그러면 DB 준비는 끝이고,

 

새롭게 생성한 칼럼인 FILENAME을 JAVA 에서 사용 할 수 있게,

멤버변수를 선언하고, getter, setter 을 추가 한다.

 

 

이러면, VO 클래스도 설정 완료 이다.

 

게시글이 새롭게 작성 될 때, 같이 파일이 업로드 되기 때문에,

MODEL 파트의 비즈니스 메서드인 insert() 메서드가 사용 되는데,

아래의 코드를 확인해보자.

 

 

FILENAME 칼럼에 파일명이 insert 되어야 하기 때문에,

bVO.getFileUpload().getOriginalFilename() 을 update() 메서드의 인자로 넣은 것을 확인 할 수 있다.

 

위와 같이 getOriginalFilename() 메서드를 사용해도 되고,

 

 

Controller 에서 위와 같이 fileName을 구해 놓았으니,

 

 

fileName을 bVO에 set 하는식으로 작성해도 괜찮다.

 

V 으로 부터 fileName이 오는게 아니라, 업로드한 파일 자체가 오고,

그 업로드한 파일 자체를 Command 객체가 set 하는 상황이라,

업로드한 파일 자체의 파일 이름은 Controller 에서 직접 set 을 해주는 코드 이다.

 

 

그러면 위와 같이, 코드를 작성 할 수 있게 된다.

 

8.

특정 게시글에 업로드한 파일의 파일명이 DB에 잘 들어갔다면,

 

해당 게시글을 사용자가 클릭해서, 상세 보기를 들어가는 경우에,

 

selectOne() 을 할것이다.

 

 

9.

View 파트 코드 확인 하기.

>> insertBoard.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시글 작성 페이지</title>
</head>
<body>

<!-- enctype = "multipart/form-data 이게 있어야, 파일 전달이 된다. -->

<form action = "insertBoard.do" method = "post" enctype = "multipart/form-data">
	<input type = "hidden" name = "writer" value = "${member}">
	<input type = "text" name = "title" required placeholder = "제목을 작성 하세요"> <br>
	<input type = "text" name = "content" required placeholder = "내용을 작성 하세요"> <br>
	<input type = "file" name = "fileUpload"> <br>
	<input type = "submit" value = "글 작성 하기">
</form>

<hr>

<a href = "main.do">메인으로 돌아가기</a>

</body>
</html>

 

 

enctype = "multipart/form-data"

 

위의 코드가 반드시 작성 되어 있어야, 파일 업로드가 가능하다.

 

enctype 이란 ?

>> "전송 데이터 형식" 을 의미 한다.

 

10.

해당 게시글에 이미 업로드한 파일을 수정 하기.

 

파일을 수정 하는것은 비즈니스 메서드의 update() 에 해당 한다.

 

해당 부분을 수정 하면 된다.

 

 

UpdateBoardController 도 수정 하기.

 

 

detailBoard.jsp도 수정 하기.

 

 

11.

웹 브라우저에서 확인 하기.

 

 

 

 

 

 

 

 

 

 

이미지를 새로 업로드 하지 않으면, 기존의 이미지와 같은 이미지가 나오게 된다.

 

 

 

기존의 파일과 다른 파일을 업로드 하고 수정을 하면, 새로운 파일이 업로드된 모습을 확인 할 수 있다.

 

 

이미지를 아예 업로드를 안한 경우에는, 디폴트 이미지로 위의 이미지가 나오게 된다.

 

 

디폴트 이미지는, bdata 객체 == 게시글 에 프로퍼티인 filename이 null 이면,

이미지를 images 폴더 내부에 있는 default.jpg 로 보이게 설정 했다.

 

근데, 이 설정을 View 에서 해주지 않고,

Controller 에서 set 해주는 식으로 설계를 해도 괜찮다.

 

 

이런식으로 코드를 작성해도 된다.

반응형