Skip to content

Commit

Permalink
feat: Board 파일 업로드 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
2Jin1031 committed Nov 24, 2024
1 parent edf5f05 commit d95aff4
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 32 deletions.
2 changes: 1 addition & 1 deletion backend/backup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ CREATE TABLE IF NOT EXISTS `board` (
`content` text,
`view_count` int DEFAULT '0',
`writer` varchar(255) DEFAULT NULL,
`file` varchar(255) DEFAULT NULL,
`fileList` TEXT DEFAULT NULL,
`create_date` datetime DEFAULT CURRENT_TIMESTAMP,
`category` varchar(50) DEFAULT NULL,
`department_id` bigint DEFAULT NULL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequiredArgsConstructor
Expand All @@ -29,9 +31,10 @@ public class BoardController {
private final BoardService boardService;

@Operation(summary = "게시판 생성 API 입니다.", description = "게시판 생성입니다.")
@PostMapping
public ResponseEntity<Long> createBoard(@RequestBody BoardReqDto boardReqDto) {
Long boardId = boardService.saveBoard(boardReqDto);
@PostMapping(consumes = "multipart/form-data")
public ResponseEntity<Long> createBoard(@RequestPart(value = "boardReqDto") BoardReqDto boardReqDto,
@RequestPart(value = "boardFiles") List<MultipartFile> multipartFileList) {
Long boardId = boardService.saveBoard(boardReqDto, multipartFileList);
return new ResponseEntity<>(boardId, HttpStatus.OK);
}

Expand Down Expand Up @@ -60,8 +63,9 @@ public ResponseEntity<BoardResDto> getBoard(@PathVariable(name = "boardId") Long
@Operation(summary = "게시판 정보 업데이트 API", description = "게시판 정보 업데이트")
@PostMapping("/{boardId}")
public ResponseEntity<BoardResDto> updateBoard(@PathVariable(name = "boardId") Long boardId,
@RequestBody BoardReqDto boardReqDto) {
BoardResDto boardResDto = boardService.updateBoard(boardId, boardReqDto);
@RequestPart(value = "boardReqDto") BoardReqDto boardReqDto,
@RequestPart(value = "boardFiles") List<MultipartFile> multipartFileList) {
BoardResDto boardResDto = boardService.updateBoard(boardId, boardReqDto, multipartFileList);
return new ResponseEntity<>(boardResDto, HttpStatus.OK);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.example.backend.board.domain.dto;

import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -11,16 +12,20 @@ public class BoardReqDto {
private String title;
private String content;
private String writer;
private String file;
private List<String> fileList;
private String category;

@Builder
private BoardReqDto(String title, String content, String writer,
String file, String category) {
List<String> fileList, String category) {
this.title = title;
this.content = content;
this.writer = writer;
this.file = file;
this.fileList = fileList;
this.category = category;
}

public void setFileList(List<String> fileList) {
this.fileList = fileList;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.example.backend.board.domain.dto;

import java.time.LocalDateTime;
import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -14,18 +15,18 @@ public class BoardResDto {
private String title;
private String content;
private String writer;
private String file;
private List<String> fileList;
private LocalDateTime createDate;
private String category;

@Builder
private BoardResDto(Long id, String title, String content, String writer,
String file, LocalDateTime createDate, String category) {
List<String> fileList, LocalDateTime createDate, String category) {
this.id = id;
this.title = title;
this.content = content;
this.writer = writer;
this.file = file;
this.fileList = fileList;
this.createDate = createDate;
this.category = category;
}
Expand All @@ -36,7 +37,7 @@ public static BoardResDto of(Board board) {
.title(board.getTitle())
.content(board.getContent())
.writer(board.getWriter())
.file(board.getFile())
.fileList(board.getFileList())
.createDate(board.getCreatedDateTime())
.category(board.getCategory().name())
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.example.backend.board.domain.entity;

import jakarta.persistence.*;
import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.example.backend.board.domain.dto.BoardReqDto;
import org.example.backend.global.config.BaseEntity;
import org.example.backend.global.config.StringListConverter;

@Entity
@Getter
Expand All @@ -30,20 +32,21 @@ public class Board extends BaseEntity {
@Column(name = "writer")
private String writer;

@Column(name = "file")
private String file;
@Convert(converter = StringListConverter.class)
@Column(name = "file_list", length = 1000)
private List<String> fileList;

@Enumerated(EnumType.STRING)
@Column(name = "category")
private Category category;

@Builder
private Board(String title, String content, String writer,
String file, Category category) {
List<String> fileList, Category category) {
this.title = title;
this.content = content;
this.writer = writer;
this.file = file;
this.fileList = fileList;
this.category = category;
this.viewCount = 0;
}
Expand All @@ -53,7 +56,7 @@ public static Board of(BoardReqDto dto) {
.title(dto.getTitle())
.content(dto.getContent())
.writer(dto.getWriter())
.file(dto.getFile())
.fileList(dto.getFileList())
.category(Category.valueOf(dto.getCategory()))
.build();
}
Expand All @@ -62,7 +65,7 @@ public void update(BoardReqDto dto) {
this.title = dto.getTitle();
this.content = dto.getContent();
this.writer = dto.getWriter();
this.file = dto.getFile();
this.fileList = dto.getFileList();
this.category = Category.valueOf(dto.getCategory());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum BoardExceptionType implements BaseExceptionType {
REQUIRED_TITLE(BAD_REQUEST, "제목은 필수 입력값입니다."),
REQUIRED_CONTENT(BAD_REQUEST, "내용은 필수 입력값입니다."),
REQUIRED_DEPARTMENT_ID(BAD_REQUEST, "부서 ID는 필수 입력값입니다."),
REQUIRED_FILE(BAD_REQUEST, "파일이 비어 있습니다.")
;

private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static org.example.backend.board.exception.BoardExceptionType.NOT_FOUND_BOARD;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.example.backend.board.domain.dto.BoardReqDto;
import org.example.backend.board.domain.dto.BoardResDto;
Expand All @@ -10,20 +12,27 @@
import org.example.backend.board.exception.BoardException;
import org.example.backend.board.exception.BoardExceptionType;
import org.example.backend.board.repository.BoardRepository;
import org.example.backend.global.config.S3Uploader;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BoardService {
private final BoardRepository boardRepository;
private final S3Uploader s3Uploader;
private static final String dirName = "image";

@Transactional
public Long saveBoard(BoardReqDto boardReqDto) {
public Long saveBoard(BoardReqDto boardReqDto, List<MultipartFile> multipartFileList) {
validateUserRequiredFields(boardReqDto);

fileUpload(boardReqDto, multipartFileList);

Board board = Board.of(boardReqDto);
Board savedBoard = boardRepository.save(board);
return savedBoard.getId();
Expand Down Expand Up @@ -54,7 +63,8 @@ public Page<BoardResDto> getBoardsByCategory(Category category, Pageable pageabl
}

@Transactional
public BoardResDto updateBoard(Long boardId, BoardReqDto boardReqDto) {
public BoardResDto updateBoard(Long boardId, BoardReqDto boardReqDto, List<MultipartFile> multipartFileList) {
fileUpload(boardReqDto, multipartFileList);
Board board = findBoardById(boardId);
board.update(boardReqDto);
return BoardResDto.of(board);
Expand All @@ -70,4 +80,18 @@ private Board findBoardById(Long boardId) {
return boardRepository.findById(boardId)
.orElseThrow(() -> new BoardException(NOT_FOUND_BOARD));
}

private void fileUpload(BoardReqDto boardReqDto, List<MultipartFile> multipartFileList) {
List<String> updateImageUrlList = new ArrayList<>();
if (!multipartFileList.isEmpty()) {
for (MultipartFile multipartFile : multipartFileList) {
if (multipartFile.isEmpty()) {
throw new BoardException(BoardExceptionType.REQUIRED_FILE);
}
String uploadImageUrl = s3Uploader.upload(multipartFile, dirName);
updateImageUrlList.add(uploadImageUrl);
}
boardReqDto.setFileList(updateImageUrlList);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.example.backend.global.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import java.util.List;

@Converter
public class StringListConverter implements AttributeConverter<List<String>, String> {

private final ObjectMapper mapper = new ObjectMapper();

@Override
public String convertToDatabaseColumn(List<String> dataList) {
try {
return mapper.writeValueAsString(dataList);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

@Override
public List<String> convertToEntityAttribute(String data) {
try {
return mapper.readValue(data, List.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
22 changes: 11 additions & 11 deletions backend/src/main/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ VALUES


-- Board 더미 데이터 (10개)
INSERT INTO board (title, content, view_count, writer, file, category)
INSERT INTO board (title, content, view_count, writer, file_list, category)
VALUES
('첫 번째 게시글', '게시글 내용 1', 10, '작성자1', 'file1.txt', 'undergraduate'),
('두 번째 게시글', '게시글 내용 2', 20, '작성자2', 'file2.txt', 'graduate'),
('세 번째 게시글', '게시글 내용 3', 30, '작성자3', 'file3.txt', 'employment'),
('네 번째 게시글', '게시글 내용 4', 40, '작성자4', 'file4.txt', 'scholarship'),
('다섯 번째 게시글', '게시글 내용 5', 50, '작성자5', 'file5.txt', 'undergraduate'),
('여섯 번째 게시글', '게시글 내용 6', 60, '작성자6', 'file6.txt', 'graduate'),
('일곱 번째 게시글', '게시글 내용 7', 70, '작성자7', 'file7.txt', 'employment'),
('여덟 번째 게시글', '게시글 내용 8', 80, '작성자8', 'file8.txt', 'scholarship'),
('아홉 번째 게시글', '게시글 내용 9', 90, '작성자9', 'file9.txt', 'undergraduate'),
('열 번째 게시글', '게시글 내용 10', 100, '작성자10', 'file10.txt','graduate');
('첫 번째 게시글', '게시글 내용 1', 10, '작성자1', '["file1.txt", "file2.txt"]', 'undergraduate'),
('두 번째 게시글', '게시글 내용 2', 20, '작성자2', '["file3.txt", "file4.txt"]', 'graduate'),
('세 번째 게시글', '게시글 내용 3', 30, '작성자3', '["file5.txt", "file6.txt"]', 'employment'),
('네 번째 게시글', '게시글 내용 4', 40, '작성자4', '["file7.txt", "file8.txt"]', 'scholarship'),
('다섯 번째 게시글', '게시글 내용 5', 50, '작성자5', '["file9.txt", "file10.txt"]', 'undergraduate'),
('여섯 번째 게시글', '게시글 내용 6', 60, '작성자6', '["file11.txt", "file12.txt"]', 'graduate'),
('일곱 번째 게시글', '게시글 내용 7', 70, '작성자7', '["file13.txt", "file14.txt"]', 'employment'),
('여덟 번째 게시글', '게시글 내용 8', 80, '작성자8', '["file15.txt", "file16.txt"]', 'scholarship'),
('아홉 번째 게시글', '게시글 내용 9', 90, '작성자9', '["file17.txt", "file18.txt"]', 'undergraduate'),
('열 번째 게시글', '게시글 내용 10', 100, '작성자10', '["file19.txt", "file20.txt"]', 'graduate');

0 comments on commit d95aff4

Please sign in to comment.