Sekkison SpringBoot project - 07

ILCHAN AHN·2023년 3월 20일
0

Sekkison

목록 보기
6/13

Sekkison Project

파일업로드

유저의 프로필사진을 저장하기 위한 폴더를 Sekkison 폴더 바로 밑에 만들어 주었다.

spring.servlet.multipart.max-file-size=5MB
spring.servlet.multipart.max-request-size=20MB
file.upload-dir=upload
app.upload.path=upload

multipart file의 용량을 지정하고 업로드되는 경로를 지정해주었다. 유저 프로필을 저장하기 위한 폴더를 upload로 만들었으니 폴더명을 넣어주면 된다.

UserFileController

@RestController
@RequestMapping("/userFiles")
@RequiredArgsConstructor
public class UserFileController {

    private final UserFileService userFileService;

    // 파일저장 경로
    @Value("${file.upload-dir}")
    private String uploadDir;

    // 프로필 업로드
    @ResponseBody
    @PostMapping("/upload")
    public ResponseForm uploadFile(@RequestParam("file") MultipartFile file,
                                             @RequestParam("userId") Long userId) {
        try {
            return userFileService.uploadFile(userId, file);
        } catch (IOException e) {
            return null;
        }
    }
}

Controller에서 업로드는 userId를 기준으로 사진을 MultipartFile file에 담아 매개변수로 받았다.

UserFileService

@Service
@Transactional
@RequiredArgsConstructor
public class UserFileService {

    // 파일 경로
    @Value("${file.upload-dir}")
    private String uploadDir;

    // 이미지 파일은 최대 5MB
    private static final long MAX_IMAGE_SIZE = 5242880;

    private final UserFileRepository userFileRepository;

    // 프로필 올리기
    public ResponseForm uploadFile(Long userId, MultipartFile file) throws IOException {
        ResponseForm responseForm = new ResponseForm();

        // 파일이 없거나 빈파일이면 레파지토리에서 userId 기준으로 탐색
        if (file.isEmpty() || "".equals(file.getName())) {
            UserFile userFile = userFileRepository.findByUserId(userId).orElse(null);

            // 파일이 없고 기본 파일이 아니면 파일 삭제 후 기본 파일로 저장
            if (userFile != null && !userFile.getFile().equals("default.jpg"))
                new File(uploadDir + "/" + userFile.getFile()).delete();
            userFile.setFile("default.jpg");
            userFileRepository.save(userFile);
            return responseForm.setSuccess(null);
        }

        // 이미지 크기 제한 체크
        if (file.getSize() > MAX_IMAGE_SIZE) {
            throw new RuntimeException("이미지 크기가 너무 큽니다.");
        }

        // 이미지 저장
        String fileName = writeFile(file);
        UserFile userFile = userFileRepository.findByUserId(userId).orElse(null);

        // 파일이 없고 기본 파일이 아니면 저장
        if (userFile != null && !userFile.getFile().equals("default.jpg"))
            new File(uploadDir + "/" + userFile.getFile()).delete();

        userFile.setFile(fileName);
        userFileRepository.save(userFile);

        return responseForm.setSuccess(null);
    }

    private String writeFile(MultipartFile file) throws IOException {
        String extension = com.google.common.io.Files.getFileExtension(file.getOriginalFilename());
        String fileName = UUID.randomUUID().toString() + "." + extension;
        byte[] fileContent = file.getBytes();

        String filePath = uploadDir + "/" + fileName;

        Path path = Paths.get(filePath);
        Files.write(path, fileContent);
        return fileName;
    }

}

MultipartFile을 사용하여 파일 업로드를 처리하고, 해당 파일을 로컬 파일 시스템에 저장하는 기능을 구현하였다.

1. 먼저, 업로드된 파일의 확장자를 가져와서 변수 extension에 저장한다. 이를 위해 Google Guava 라이브러리의 Files 클래스의 getFileExtension() 메서드를 사용하였다
2. 사용자가 업로드한 파일이 이름이 기본 프로필 파일과 이름이 같거나 다른 유저의 파일과 같을 경우 문제가 생기기 때문에 UUID를 사용하여 랜덤한 파일 이름을 생성하였다.
3. 업로드된 파일의 내용을 byte 배열로 가져와 fileContent 변수에 저장한다.
4. 로컬 파일 시스템에 파일을 저장하기 위해, 저장할 파일의 경로를 filePath 변수에 저장한다. 이는 uploadDir 변수에 파일 이름을 더해 경로를 만들어주게 된다.

Sekkison에서 유저가 파일을 올리지 않으면 기본 이미지로 표현되기 때문에 upload 폴더에 기본 이미지를 넣어주고, userfile 객체가 null일 경우 이미지를 넣어주었다.

따라서 userfile이 null이 아니고 기본이미지가 아닌 경우 유저가 원하는 사진을 넣으면 프로필 사진이 변경된다.

profile
백엔드 개발자를 꿈꿉니다

0개의 댓글