프론트에서 MultiFile과 포스트 내용을 받아왔으니 백엔드에서 처리해주어야한다. 처리 로직은 다음과 같다.
1. 게시물을 저장할 Post 엔티티와 그 게시글의 파일들을 저장할 PostFile 엔티티생성
2. Jwt의 유저 내용과 전달받은 내용을 기반으로 Post 저장
3. 자바의 FileUpload 기능을 사용하여 로컬에 파일 저장
1. Post, PostFile Entity 생성
@Entity
@Data
@NoArgsConstructor
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long id;
@ManyToOne
@JoinColumn(name = "made_user")
private User user;
private String content;
@Builder
public Post(User user, String content) {
this.user = user;
this.content = content;
}
}
@Entity
@Data
@NoArgsConstructor
public class PostFile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_file_id")
private Long id;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@Column(name = "post_file_index")
private Long postFileIndex;
@Column(name = "post_file_url")
private String postFileUrl;
@Builder
public PostFile(Post post, User user, Long postFileIndex, String postFileUrl) {
this.post = post;
this.user = user;
this.postFileIndex = postFileIndex;
this.postFileUrl = postFileUrl;
}
}
- Post의 칼럼들은 다음과 같다.
1. User : 게시글 저장 유저
2. content : 게시글 내용
- PostFile의 칼럼들은 다음과 같다.
1. Post : 소속된 게시글
2. User : 게시글 저장 유저
3. postFileIndex : 파일 인덱스 번호
4. postFileUrl : 파일 저장 Url
2. UploadPostRequestDto 작성
@Data
public class UploadPostRequestDto {
@NotNull(message = "사진은 필수 항목입니다.")
@Size(min = 1)
private List<MultipartFile> file;
private String content;
}
3. FileUploader 작성
@Component
@Slf4j
@RequiredArgsConstructor
public class FileUploader {
@Value("${path.repositoryPath}")
private String repositoryPath;
/**
* 파일과 저장할 폴더를 지정하면 파일을 저장해주는 메서드
*/
public void saveFile(String email, Long id, String type, MultipartFile file) {
Path copyOfLocation = Paths.get(repositoryPath + File.separator + type + File.separator + email + File.separator + id + File.separator + StringUtils.cleanPath(file.getOriginalFilename()));
Path copyOfDirectory = Paths.get(repositoryPath + File.separator + type + File.separator + email + File.separator + id);
try {
Files.createDirectories(copyOfDirectory);
Files.copy(file.getInputStream(), copyOfLocation, StandardCopyOption.REPLACE_EXISTING);
log.info("File {} is saved at Directory [{}]", file.getOriginalFilename(), copyOfLocation);
} catch (IOException e) {
log.debug("{}", e.getMessage());
}
}
}
- 저장할 유저의 email, 게시글 번호, 저장할 타입, 그리고 파일을 받아와 파일을 저장한다.
4. PostService 작성
@Service
@Slf4j
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
private final PostFileRepository postFileRepository;
private final FileUploader fileUploader;
@Transactional
public void uploadPost(User user, UploadPostRequestDto requestDto) {
List<MultipartFile> files = requestDto.getFile();
// POST Entity 생성 및 저장
Post savedPost = Post
.builder()
.content(requestDto.getContent())
.user(user)
.build();
postRepository.save(savedPost);
// POST Image Entity 생성 및 저장
AtomicInteger index = new AtomicInteger();
files.stream()
.forEach((file) -> {
String dbPathLocation = "/post/" + user.getEmail() + "/" + savedPost.getId() + "/" + file.getOriginalFilename();
PostFile savePostFile = PostFile.builder()
.postFileIndex((long) index.getAndIncrement())
.postFileUrl(dbPathLocation)
.post(savedPost)
.user(user)
.build();
fileUploader.saveFile(user.getEmail(), savedPost.getId(), "post", file);
postFileRepository.save(savePostFile);
});
}
}
- 차례로 Post 엔티티와 PostFile 엔티티를 생성하여 그 안에 값들을 저장하고 로컬에 파일을 저장한다.
5. PostController 작성
@RestController
@Slf4j
@RequiredArgsConstructor
public class PostController {
private final PostService postService;
@PostMapping("/post")
public ResponseEntity uploadPost(@CurrentUser User user, @Valid @ModelAttribute UploadPostRequestDto requestDto, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
String errorMsg = bindingResult.getFieldError().getDefaultMessage();
return ResponseEntity.badRequest().body(errorMsg);
}
try {
postService.uploadPost(user, requestDto);
return ResponseEntity.ok().body("게시물이 성공적으로 업로드 되었습니다.");
} catch (Exception e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
}
'Web > 인스타 클론 코딩' 카테고리의 다른 글
[인스타그램 클론코딩] 07. 팔로우 기능 구현(Back-End) (0) | 2023.02.02 |
---|---|
[인스타그램 클론코딩] 07. 팔로우 기능 구현(Front-End) (0) | 2023.02.02 |
[인스타그램 클론코딩] 06. 게시글 Posting 구현(Front-End) (0) | 2023.02.02 |
[인스타그램 클론코딩] 05. 기본 화면 구성(Front-End) (0) | 2023.02.02 |
[인스타그램 클론코딩] 04. JWT 필터 구현(Front-End) (0) | 2023.02.01 |