Search

[스프링 게시판] 파일 업로드

@3/21/2023

UploadFile 엔티티 생성

ERD 수정
엔티티 다이어그램 수정

설정

application.yaml에 다음 추가
파일별, 요청별 최대 크기 지정 및 파일 저장 위치 지정
spring: servlet: multipart: max-file-size: 5MB max-request-size: 30MB file: path: /Users/gyuray/dev/projects/forum/src/main/resources/files/
Java
복사

FileManager 클래스 추가

package dev.gyuray.forum.controller; import dev.gyuray.forum.domain.UploadFile; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Component public class FileManager { @Value("${file.path}") private String filePath; public List<UploadFile> storeFiles(List<MultipartFile> multipartFiles) throws IOException { List<UploadFile> storedFiles = new ArrayList<>(); for (MultipartFile multipartFile : multipartFiles) { if (!multipartFile.isEmpty()) { storedFiles.add(storeFile(multipartFile)); } } return storedFiles; } public UploadFile storeFile(MultipartFile multipartFile) throws IOException { String originalFilename = multipartFile.getOriginalFilename(); String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); String storedFileName = UUID.randomUUID() + ext; multipartFile.transferTo(new File(filePath + storedFileName)); return new UploadFile(originalFilename, storedFileName); } }
Java
복사

영속성 전이(cascade.ALL)가 적용이 안 되는 문제

@PostMapping public String createPost( @Validated @ModelAttribute PostForm postForm, BindingResult bindingResult, @SessionAttribute(value = "loginUser") User loginUser ) throws IOException { if (bindingResult.hasErrors()) { return "posts/postForm"; } Long postId = postService.addPost(postForm, loginUser); Post post = postService.findPostById(postId); List<MultipartFile> uploadFiles = postForm.getUploadFiles(); List<UploadFile> storedFiles = fileManager.storeFiles(uploadFiles); for (UploadFile storedFile : storedFiles) { storedFile.addToPost(post); } for (UploadFile uploadFile : post.getUploadFiles()) { log.info("uploadFile.getOriginalFileName() = {}", uploadFile.getOriginalFileName()); log.info("uploadFile.getStoredFileName() = {}", uploadFile.getStoredFileName()); } return "redirect:/posts"; }
Java
복사
위처럼 컨트롤러에서 파일 업로드를 처리했는데, uploadfile이 DB에 들어가지를 않음
당연하게도, 이미 db 트랜잭션은 Long postId = postService.addPost(postForm, loginUser); 단계에서 끝이 났기 때문에 아무리 post를 받아서 수정해도 dirty checking을 통한 수정 및 cascade가 안 되는 것이었음
아래처럼 service단으로 옮겨서 처리함
@Transactional public Long addPost(PostForm postForm, User writer) throws IOException { Post post = new Post(); post.setUser(writer); post.setTitle(postForm.getTitle()); post.setContent(postForm.getContent()); List<MultipartFile> multipartFiles = postForm.getUploadFiles(); if (multipartFiles != null) { List<UploadFile> uploadFiles = fileManager.storeFiles(multipartFiles); for (UploadFile uploadFile : uploadFiles) { uploadFile.addToPost(post); } } postRepository.save(post); return post.getId(); }
Java
복사

결과 화면

관련 커밋

23ad576e959dc047e6fc03c2f8f08664600af7e2
commit