Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] course 엔티티 수정 + 코스 추천 리스트, IsHidden 구현 + 이미지 업로드 프로토타입 구현 #12

Merged
merged 13 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package togathering.Plogging.Uploader;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Optional;

@Slf4j
@RequiredArgsConstructor // final 멤버변수가 있으면 생성자 항목에 포함시킴
@Component
@Service
public class S3Uploader {

private final AmazonS3Client amazonS3Client;

@Value("${cloud.aws.s3.bucket}")
private String bucket;

// MultipartFile을 전달받아 File로 전환한 후 S3에 업로드
public String upload(MultipartFile multipartFile, String dirName) throws IOException {
File uploadFile = convert(multipartFile)
.orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File 전환 실패"));
return upload(uploadFile, dirName);
}

private String upload(File uploadFile, String dirName) {
String fileName = dirName + "/" + uploadFile.getName();
String uploadImageUrl = putS3(uploadFile, fileName);

removeNewFile(uploadFile); // 로컬에 생성된 File 삭제 (MultipartFile -> File 전환 하며 로컬에 파일 생성됨)

return uploadImageUrl; // 업로드된 파일의 S3 URL 주소 반환
}

private String putS3(File uploadFile, String fileName) {
amazonS3Client.putObject(
new PutObjectRequest(bucket, fileName, uploadFile)
.withCannedAcl(CannedAccessControlList.PublicRead) // PublicRead 권한으로 업로드 됨
);
return amazonS3Client.getUrl(bucket, fileName).toString();
}

private void removeNewFile(File targetFile) {
if(targetFile.delete()) {
log.info("파일이 삭제되었습니다.");
}else {
log.info("파일이 삭제되지 못했습니다.");
}
}

private Optional<File> convert(MultipartFile file) throws IOException {
File convertFile = new File(file.getOriginalFilename());
if(convertFile.createNewFile()) {
try (FileOutputStream fos = new FileOutputStream(convertFile)) {
fos.write(file.getBytes());
}
return Optional.of(convertFile);
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.http.HttpStatus;
import togathering.Plogging.apiPayload.code.BaseCode;
import togathering.Plogging.apiPayload.code.ReasonDTO;
import togathering.Plogging.domain.PloggingCourse;

@Getter
@AllArgsConstructor
Expand All @@ -29,6 +30,10 @@ public enum SuccessStatus implements BaseCode {
PLOGGING_COURSE_LIST_OK(HttpStatus.OK, 200, "코스 리스트 조회 성공!"),
PLOGGING_COURSE_INFO_OK(HttpStatus.OK, 200, "코스 정보 조회 성공!"),
PLOGGING_COURSE_REVIEW_OK(HttpStatus.OK, 200, "코스 리뷰 생성 성공!"),
PLOGGING_COURSE_TAG_MODIFY_OK(HttpStatus.OK, 200, "코스 태그 수정 성공!"),
PLOGGING_COURSE_MODIFY_OK(HttpStatus.OK, 200, "코스 수정 성공!"),
PLOGGING_COURSE_RECOMMEND_OK(HttpStatus.OK, 200, "코스 추천 성공!"),

// 회원가입 관련
REGISTER_JOIN_OK(HttpStatus.OK, 200, "회원가입 성공!");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import togathering.Plogging.apiPayload.code.status.SuccessStatus;
import togathering.Plogging.app.dto.PloggingCourseDTO;
import togathering.Plogging.app.dto.PloggingGroupReviewDTO;
import togathering.Plogging.converter.PCsConverter;
import togathering.Plogging.domain.mapping.PloggingGroupReview;
import togathering.Plogging.service.PCsQueryService;

Expand Down Expand Up @@ -42,6 +43,27 @@ public ApiResponse<PloggingCourseDTO.ResponsePloggingCourseDTO> createPloggingCo
return ApiResponse.of(SuccessStatus.PLOGGING_COURSE_CREATE_OK, responseDTO);
}

@PostMapping("/courses/{course_id}/modify")
public ApiResponse<PloggingCourseDTO.ResponsePloggingCourseDTO> modifyPloggingCourse(
@PathVariable String course_id,
@RequestBody PloggingCourseDTO.RequestPloggingCourseDTO dto
){
PloggingCourseDTO.ResponsePloggingCourseDTO responseDTO = pcsQueryService.modifyCourse(dto, Long.parseLong(course_id));


return ApiResponse.of(SuccessStatus.PLOGGING_COURSE_MODIFY_OK, responseDTO);
}

@PostMapping("/course/{course_id}/modify-tag")
public ApiResponse<PloggingCourseDTO.ResponseModifyCourseTagDTO> modifyCourseTag(
@PathVariable String course_id,
@RequestBody PloggingCourseDTO.RequestModifyCourseTagDTO dto){

PloggingCourseDTO.ResponseModifyCourseTagDTO responseDTO = pcsQueryService.modifyCourseTag(dto, Long.parseLong(course_id));

return ApiResponse.of(SuccessStatus.PLOGGING_COURSE_TAG_MODIFY_OK, responseDTO);
}

// plogging course review 사진 업로드하기
@PostMapping("/course/{course_id}/photos")
public void uploadPGCsPicture(@RequestBody MultipartFile file){
Expand All @@ -50,12 +72,33 @@ public void uploadPGCsPicture(@RequestBody MultipartFile file){

// plogging group review 생성하기
@PostMapping("/course/{course_id}/review")
public ApiResponse<PloggingGroupReviewDTO.ResponsePloggingGroupReviewDTO> reviewPGCourse(
@RequestBody PloggingGroupReviewDTO.RequestPloggingGroupReviewDTO dto,
@PathVariable String course_id){
public String reviewCourse(
@RequestPart("images") List<MultipartFile> images,
@RequestParam("review") String reivew
){
PloggingGroupReviewDTO.ResponsePloggingGroupReviewDTO responseDTO =
pcsQueryService.createPloggingGroupReivew(PCsConverter.toRequestPloggingGroupReviewDTO(reivew, images));

return reivew;
}

@GetMapping("/course/recommend")
public ApiResponse<List<PloggingCourseDTO.ResponsePloggingCourseDTO>> recommendCourse(
@RequestBody PloggingCourseDTO.RequestRecommendCourseDTO dto
){
List<PloggingCourseDTO.ResponsePloggingCourseDTO> recommendList =
pcsQueryService.getRecommendCourseList(dto.getTag());

return ApiResponse.of(SuccessStatus.PLOGGING_COURSE_LIST_OK, recommendList);
}

PloggingGroupReviewDTO.ResponsePloggingGroupReviewDTO responseDTO = pcsQueryService.createPloggingGroupReivew(dto);
@GetMapping("/course/search")
public ApiResponse<List<PloggingCourseDTO.ResponsePloggingCourseDTO>> searchCourse(
@RequestBody PloggingCourseDTO.RequestSearchCourseDTO dto
){
List<PloggingCourseDTO.ResponsePloggingCourseDTO> resultCourseList =
pcsQueryService.getCourseListSearchBy(dto.getWord());

return ApiResponse.of(SuccessStatus.PLOGGING_COURSE_REVIEW_OK, responseDTO);
return ApiResponse.of(SuccessStatus.PLOGGING_COURSE_LIST_OK, resultCourseList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public class PloggingCourseDTO {
public static class RequestPloggingCourseDTO {
private String metadata;
private String title;
private Long time;
private Long duration;
private String tag;
}

@Getter
Expand All @@ -17,11 +20,40 @@ public static class GetPloggingCourseInfoDTO {
private Long course_id;
private String metadata;
private String title;

private Long time;
private Long duration;
private String tag;
}

@Getter
@Builder
public static class ResponsePloggingCourseDTO{
private Long course_id;
}

@Getter
@NoArgsConstructor
public static class RequestModifyCourseTagDTO{
private String tag;
}

@Getter
@Builder
public static class ResponseModifyCourseTagDTO{
private Long course_id;
private String tag;
}

@Getter
@NoArgsConstructor
public static class RequestRecommendCourseDTO{
private String tag;
}

@Getter
@NoArgsConstructor
public static class RequestSearchCourseDTO{
private String word;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;


public class PloggingGroupReviewDTO {
@Getter
@Builder
public static class RequestPloggingGroupReviewDTO {
private Long group_id;
private Long user_id;
private String content;
private int cleanliness;
private int reward;
private int like;
List<MultipartFile> images;
}

@Getter
@Builder
public static class ResponsePloggingGroupReviewDTO {
private Long review_id;
private String content;
}
}
36 changes: 36 additions & 0 deletions backend/src/main/java/togathering/Plogging/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package togathering.Plogging.config;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import net.bytebuddy.utility.nullability.AlwaysNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;

@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;

@Value("${cloud.aws.region.static}")
private String region;

@Bean
public AmazonS3 amazonS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(region)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package togathering.Plogging.converter;

import org.springframework.web.multipart.MultipartFile;
import togathering.Plogging.app.dto.PloggingCourseDTO;
import togathering.Plogging.app.dto.PloggingGroupReviewDTO;
import togathering.Plogging.domain.PloggingCourse;
import togathering.Plogging.domain.mapping.PloggingGroupReview;

import java.util.List;

public class PCsConverter {
public static PloggingCourseDTO.GetPloggingCourseInfoDTO toPloggingCourseInfoDTO(PloggingCourse ploggingCourse) {
return PloggingCourseDTO.GetPloggingCourseInfoDTO.builder()
Expand All @@ -20,10 +23,50 @@ public static PloggingCourseDTO.ResponsePloggingCourseDTO toResponsePloggingCour
.build();
}

public static PloggingCourse toUpdatePloggingCourseTag(PloggingCourseDTO.RequestModifyCourseTagDTO request, PloggingCourse ploggingCourse) {
return PloggingCourse.builder().
id(ploggingCourse.getId()).
metadata(ploggingCourse.getMetadata()).
title(ploggingCourse.getTitle()).
duration(ploggingCourse.getDuration()).
time(ploggingCourse.getTime()).
isHidden(ploggingCourse.getIsHidden()).
tag(request.getTag()).build();
}

public static PloggingCourse toUpdatePloggingCourseHidden(PloggingCourse ploggingCourse) {
return PloggingCourse.builder().
id(ploggingCourse.getId()).
metadata(ploggingCourse.getMetadata()).
title(ploggingCourse.getTitle()).
duration(ploggingCourse.getDuration()).
time(ploggingCourse.getTime()).
isHidden(!ploggingCourse.getIsHidden()).
tag(ploggingCourse.getTag()).build();
}

public static PloggingCourseDTO.ResponseModifyCourseTagDTO toResponseModifyCourseTagDTO(PloggingCourse ploggingCourse){
return PloggingCourseDTO.ResponseModifyCourseTagDTO.builder().
course_id(ploggingCourse.getId()).
tag(ploggingCourse.getTag()).
build();
}

public static PloggingGroupReviewDTO.ResponsePloggingGroupReviewDTO toResponsePloggingGroupReviewDTO(PloggingGroupReview ploggingGroupReview) {
return PloggingGroupReviewDTO.ResponsePloggingGroupReviewDTO.builder()
.review_id(ploggingGroupReview.getId())
.content(ploggingGroupReview.getContent())
.build();
}

public static PloggingGroupReviewDTO.RequestPloggingGroupReviewDTO toRequestPloggingGroupReviewDTO(String review, List<MultipartFile> images) {


return PloggingGroupReviewDTO.RequestPloggingGroupReviewDTO.builder().
group_id(1L).
user_id(2L).
reward(3).
images(images).
cleanliness(4).
build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Table(name = "plogging_course")
public class PloggingCourse extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -21,4 +22,16 @@ public class PloggingCourse extends BaseEntity {

@Lob
private String metadata;

@Column(nullable = false)
private Long duration;

@Column(nullable = false)
private Long time;

@Lob
private String tag;

@Column(nullable = false)
private Boolean isHidden;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Table(name = "plogging_group_reivew")
public class PloggingGroupReview extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -29,8 +30,8 @@ public class PloggingGroupReview extends BaseEntity {

private int reward;

@Lob
private String content;
@Column(nullable = false)
private int cleanliness;

@OneToMany(mappedBy = "ploggingGroupReview", cascade = CascadeType.ALL)
private List<PloggingGroupReviewPicture> ploggingGroupReviewPictures;
Expand Down
Loading
Loading