diff --git a/src/main/java/com/kusitms/teamc/domain/article/controller/ArticleController.java b/src/main/java/com/kusitms/teamc/domain/article/controller/ArticleController.java index 9d74ef5..adc26ad 100644 --- a/src/main/java/com/kusitms/teamc/domain/article/controller/ArticleController.java +++ b/src/main/java/com/kusitms/teamc/domain/article/controller/ArticleController.java @@ -1,21 +1,24 @@ package com.kusitms.teamc.domain.article.controller; import com.kusitms.teamc.common.dto.SliceResponseDto; +import com.kusitms.teamc.domain.article.dto.request.ArticleSaveRequestDto; import com.kusitms.teamc.domain.article.dto.response.ArticleResponseDto; import com.kusitms.teamc.domain.article.entity.Article; import com.kusitms.teamc.domain.article.repository.ArticleRepository; import com.kusitms.teamc.domain.article.service.ArticleService; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.List; @RestController @@ -30,4 +33,11 @@ public ResponseEntity getArticlesByCategory(@RequestParam("sea Slice response = articleService.getArticlesByCategory(category, pageable); return SliceResponseDto.ok(response); } + + @PostMapping(value = "", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) + public ResponseEntity saveArticle(@RequestPart ArticleSaveRequestDto requestDto, + @RequestPart(name = "file", required = false) MultipartFile file) { + articleService.saveArticle(requestDto, file); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/kusitms/teamc/domain/article/dto/request/ArticleSaveRequestDto.java b/src/main/java/com/kusitms/teamc/domain/article/dto/request/ArticleSaveRequestDto.java new file mode 100644 index 0000000..888030d --- /dev/null +++ b/src/main/java/com/kusitms/teamc/domain/article/dto/request/ArticleSaveRequestDto.java @@ -0,0 +1,4 @@ +package com.kusitms.teamc.domain.article.dto.request; + +public record ArticleSaveRequestDto(String accessToken, String category, String title, String content, String image) { +} diff --git a/src/main/java/com/kusitms/teamc/domain/article/entity/Article.java b/src/main/java/com/kusitms/teamc/domain/article/entity/Article.java index b2d267e..074fe2f 100644 --- a/src/main/java/com/kusitms/teamc/domain/article/entity/Article.java +++ b/src/main/java/com/kusitms/teamc/domain/article/entity/Article.java @@ -1,14 +1,8 @@ package com.kusitms.teamc.domain.article.entity; import com.kusitms.teamc.common.entity.BaseTimeEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; +import jakarta.persistence.*; +import lombok.*; import java.time.LocalDateTime; @@ -25,6 +19,15 @@ public class Article extends BaseTimeEntity { private Category category; private String title; private String content; + @Column(columnDefinition = "TEXT") + private String image; + @Builder + public Article(Category category, String title, String content, String image) { + this.category = category; + this.title = title; + this.content = content; + this.image = image; + } } diff --git a/src/main/java/com/kusitms/teamc/domain/article/service/ArticleService.java b/src/main/java/com/kusitms/teamc/domain/article/service/ArticleService.java index 8e97662..5197566 100644 --- a/src/main/java/com/kusitms/teamc/domain/article/service/ArticleService.java +++ b/src/main/java/com/kusitms/teamc/domain/article/service/ArticleService.java @@ -1,15 +1,23 @@ package com.kusitms.teamc.domain.article.service; +import com.kusitms.teamc.common.s3.FileService; +import com.kusitms.teamc.domain.article.dto.request.ArticleSaveRequestDto; import com.kusitms.teamc.domain.article.dto.response.ArticleResponseDto; import com.kusitms.teamc.domain.article.entity.Article; import com.kusitms.teamc.domain.article.entity.Category; import com.kusitms.teamc.domain.article.repository.ArticleRepository; +import com.kusitms.teamc.domain.member.entity.Member; +import com.kusitms.teamc.domain.member.repository.MemberRepository; +import com.kusitms.teamc.error.ErrorCode; +import com.kusitms.teamc.error.exception.custom.BusinessException; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; @Service @Slf4j @@ -18,11 +26,21 @@ public class ArticleService { private final ArticleRepository articleRepository; + private final FileService fileService; + private final MemberRepository memberRepository; + @Transactional(readOnly = true) public Slice getArticlesByCategory(String search, Pageable pageable) { Category category = Category.create(search); Slice
articles = articleRepository.findAllByCategory(category, pageable); Slice response = articles.map(a -> ArticleResponseDto.from(a)); return response; } + + public void saveArticle(ArticleSaveRequestDto requestDto, MultipartFile file) { + Category category = Category.create(requestDto.category()); + Member member = memberRepository.findByAccessToken(requestDto.accessToken()).orElseThrow(() -> new BusinessException(ErrorCode.MEMBER_NOT_FOUND)); + String profileImageUrl = fileService.uploadFile(file, member.getName()); + articleRepository.save(new Article(category, requestDto.title(), requestDto.content(), profileImageUrl)); + } } diff --git a/src/main/java/com/kusitms/teamc/error/ErrorCode.java b/src/main/java/com/kusitms/teamc/error/ErrorCode.java index a1584cd..114416c 100644 --- a/src/main/java/com/kusitms/teamc/error/ErrorCode.java +++ b/src/main/java/com/kusitms/teamc/error/ErrorCode.java @@ -11,6 +11,7 @@ @RequiredArgsConstructor public enum ErrorCode { + MEMBER_NOT_FOUND(NOT_FOUND, "해당 회원을 찾을 수 없습니다."), TOKEN_NOT_EXIST(NOT_FOUND, "토큰이 존재하지 않습니다."), INVALID_FILE_UPLOAD(BAD_REQUEST, "잘못된 파일 업로드입니다."), INVALID_CATEGORY(BAD_REQUEST, "잘못된 카테고리입니다.");