본문 바로가기
혼자 공부하는 것들/Spring

Spring Boot 이미지업로드 (환경: gradle, java11,Spring Boot 2.6.2, thymeleaf)

by applepick 2022. 2. 14.
반응형

회원의 사진을 업로드하기 위해서 한번 구현해봤습니다.

 

 

build.gradle

dependencies {
	implementation 'commons-io:commons-io:2.6'
	...
    }

의존성을 주입해줍니다.

 

form.html

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<form action="/employee" th:object="${employeeRegisterForm}" method="post" enctype="multipart/form-data">
    <input type="file" class="form-control form-control-sm" style="margin:0 auto; width: 20%" name="file" id="file"><br>
    ....
 </div>

form에서 중요한 부분이 바로 enctype="multipart/form-data"를 추가해줘야합니다. 간단하게 설명하자면, enctype는 폼 데이터(form data)가 서버로 제출될 때 해당 데이터가 인코딩되는 방법을 명시해줍니다.

 

common.properties

## FilePath
file.path=/Users/sungmin/Desktop/~/images/user

 

properties에 파일을 저장할 위치를 선언해줍니다. 이 방법을 쓴 이유는 밑에서 설명해드리겠습니다.

 

Controller

import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

@Controller
@RequiredArgsConstructor
@Slf4j
@PropertySource("classpath:/common.properties")
public class EmployeeController {
    // 파일 저장할 위치
    @Value("${file.path}")
    private String savePath;

    //유저등록
    @PostMapping("/employee")
    String employeeRegister(HttpSession session, Model model, @RequestParam(name="file", required = false) MultipartFile file, @Valid EmployeeRegisterForm employeeRegisterForm, BindingResult bindingResult) throws IOException {

        if( !file.isEmpty() ) {   //---파일이 없으면 true를 리턴. false일 경우에만 처리함.
            String uuid = UUID.randomUUID().toString()+".jpg";
            File converFile = new File(savePath, uuid);
            file.transferTo(converFile);  //--- 저장할 경로를 설정 해당 경로는 각자 원하는 위치로 설정하면 됩니다. 다만, 해당 경로에 접근할 수 있는 권한이 없으면 에러 발생
            employeeRegisterForm.setPhotoaddr(uuid);
            Integer insertEmployeeResult = employeeRegisterService.insertEmployee(employeeRegisterForm);
            //결과
            return "redirect:/";
        }
        return "redirect:/";
    }
    ...
}

@PropertySource를 통해서 properties 설정 정보를 가져옵니다. 그후 @Value로 properties에서 path정보를 가저와 저장해놓습니다. 이렇게 한 이유는 공동작업으로 프로젝트를 진행 중인데, git 저장소에 properties파일을 배재시켜, 각 팀원들 별로 파일 저장을 본인의 디렉터리를 사용할 수 있게 하면, 충돌이 나지 않아 사용했습니다. 만약 properties를 사용하지 않고 한다면,

위 로직 안에

String savePath = "/Users/sungmin/Desktop/~/images/user";

 를 추가시켜서 작업을 해야 하는데 각 팀 원들 별로 디렉터리가 달라 수정하면 충돌이 날 수 있습니다. 이를 방지하기 위해서 사용했습니다. 이어서 설명하자면 form에서 name으로 file을 명시하여 @RequestParam로 MultipartFile를 가져와줍니다. 이후 첨부 파일이 있을 경우 파일을 저장하는데, 여기서 중요한 점이 디비에 저장할 때 유저가 등록하는 이미지의 이름을 저장하는 게 아니라 uuid를 할당해서 저장해줍니다. 저장하는 방식은 다양하지만, 유저가 업로드할 이미지 이름을 그대로 사용하면, 오류가 발생할 여지가 있기 때문에 바꿔서 저장해줍니다. 

이미지저장소
디비 저장소

이런 식으로 디비에 잘 저장하는 것을 볼 수 있습니다. 추후에 AWS S3를 사용한다면, 내용을 추가하도록하겠습니다. 감사합니다.

반응형

댓글