@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
복사