diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2f3f127..d38aae3 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -69,7 +69,7 @@ jobs: docker rm ${{ secrets.APPLICATION_NAME }} docker rmi ${{ secrets.USERNAME }}/${{ secrets.PROJECT_NAME }} docker pull ${{ secrets.USERNAME }}/${{ secrets.PROJECT_NAME }} - docker run --network=host -d -e TZ=Asia/Seoul --name ${{ secrets.APPLICATION_NAME }} ${{ secrets.USERNAME }}/${{ secrets.PROJECT_NAME }} + docker run --network=host -d -e TZ=Asia/Seoul -v ${{ secrets.IMAGE_PATH }}:/app/images --name ${{ secrets.APPLICATION_NAME }} ${{ secrets.USERNAME }}/${{ secrets.PROJECT_NAME }} diff --git a/Dockerfile b/Dockerfile index 8031ee3..481300d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,8 @@ RUN CHROME_VERSION=$(google-chrome --version | grep -oP '[0-9]+\.[0-9]+\.[0-9]+\ # 환경변수 PATH에 크롬 드라이버 경로 추가 ENV PATH="/usr/bin/chromedriver-linux64:${PATH}" +RUN mkdir -p /app/images + # 애플리케이션 JAR 파일 복사 COPY ./build/libs/inu-portal-0.0.1-SNAPSHOT.jar app.jar diff --git a/src/main/java/kr/inuappcenterportal/inuportal/controller/PostController.java b/src/main/java/kr/inuappcenterportal/inuportal/controller/PostController.java index 232a0aa..36b482c 100644 --- a/src/main/java/kr/inuappcenterportal/inuportal/controller/PostController.java +++ b/src/main/java/kr/inuappcenterportal/inuportal/controller/PostController.java @@ -64,7 +64,7 @@ public ResponseEntity> saveOnlyPost(@Valid@RequestBody PostDto @PostMapping(value = "/{postId}/images", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity> saveOnlyImage( @RequestPart List images,@PathVariable Long postId, @AuthenticationPrincipal Member member) throws IOException { log.info("이미지만 저장 호출 id:{}",postId); - return ResponseEntity.status(HttpStatus.CREATED).body(ResponseDto.of(postService.saveOnlyImage(member,postId,images),"이미지 등록 성공")); + return ResponseEntity.status(HttpStatus.CREATED).body(ResponseDto.of(postService.saveImageLocal(member,postId,images),"이미지 등록 성공")); } @@ -92,7 +92,7 @@ public ResponseEntity> updateOnlyImage(@AuthenticationPrincipa if(images==null){ images = new ArrayList<>(); } - postService.updateOnlyImage(member.getId(),postId,images); + postService.updateImageLocal(member.getId(),postId,images); return ResponseEntity.ok(ResponseDto.of(postId,"게시글 수정 성공")); } @@ -103,7 +103,7 @@ public ResponseEntity> updateOnlyImage(@AuthenticationPrincipa ,@ApiResponse(responseCode = "403",description = "이 게시글의 수정/삭제에 대한 권한이 없습니다.",content = @Content(schema = @Schema(implementation = ResponseDto.class))) }) @DeleteMapping("/{postId}") - public ResponseEntity> deletePost(@AuthenticationPrincipal Member member, @Parameter(name = "postId",description = "게시글의 id",in = ParameterIn.PATH) @PathVariable Long postId){ + public ResponseEntity> deletePost(@AuthenticationPrincipal Member member, @Parameter(name = "postId",description = "게시글의 id",in = ParameterIn.PATH) @PathVariable Long postId) throws IOException { log.info("게시글 삭제 호출 id:{}",postId); postService.delete(member.getId(),postId); return ResponseEntity.ok(ResponseDto.of(postId,"게시글 삭제 성공")); @@ -164,11 +164,11 @@ public ResponseEntity> getAllPost(@RequestParam(req ,@ApiResponse(responseCode = "404",description = "존재하지 않는 게시글입니다. / 존재하지 않는 이미지 번호입니다.",content = @Content(schema = @Schema(implementation = ResponseDto.class))) }) @GetMapping("/{postId}/images/{imageId}") - public ResponseEntity getImages(@PathVariable Long postId, @PathVariable Long imageId){ + public ResponseEntity getImages(@PathVariable Long postId, @PathVariable Long imageId) throws IOException { log.info("게시글의 이미지 가져오기 호출 id:{}",postId); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.IMAGE_PNG); - return ResponseEntity.ok().headers(httpHeaders).body(redisService.findImages(postId, imageId)); + return ResponseEntity.ok().headers(httpHeaders).body(postService.getImage(postId, imageId)); } @Operation(summary = "상단부 인기 게시글 12개 가져오기",description = "기본 호출 시 모든 글에 대한 인기 게시글 12개, 파라미터로 category를 보낼 시 카테고리의 인기글 12개가 호출됩니다.") diff --git a/src/main/java/kr/inuappcenterportal/inuportal/service/PostService.java b/src/main/java/kr/inuappcenterportal/inuportal/service/PostService.java index 45498b8..8084947 100644 --- a/src/main/java/kr/inuappcenterportal/inuportal/service/PostService.java +++ b/src/main/java/kr/inuappcenterportal/inuportal/service/PostService.java @@ -12,6 +12,7 @@ import kr.inuappcenterportal.inuportal.exception.ex.MyException; import kr.inuappcenterportal.inuportal.repository.*; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -21,6 +22,9 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.util.Comparator; import java.util.List; @@ -37,6 +41,9 @@ public class PostService { private final CategoryRepository categoryRepository; private final RedisService redisService; + @Value("${imagePath}") + private String path; + @Transactional public Long saveOnlyPost(Member member, PostDto postSaveDto) throws NoSuchAlgorithmException { @@ -49,24 +56,31 @@ public Long saveOnlyPost(Member member, PostDto postSaveDto) throws NoSuchAlgori postRepository.save(post); return post.getId(); } + + @Transactional - public Long saveOnlyImage(Member member, Long postId, List imageDto) throws IOException { + public Long saveImageLocal(Member member, Long postId, List images ) throws IOException { Post post = postRepository.findById(postId).orElseThrow(()->new MyException(MyErrorCode.POST_NOT_FOUND)); if(!post.getMember().getId().equals(member.getId())){ throw new MyException(MyErrorCode.HAS_NOT_POST_AUTHORIZATION); } long imageCount; - if(imageDto==null){ - imageCount = 0; - } - else{ - imageCount = imageDto.size(); - } - if(imageDto!=null) { - redisService.saveImage(post.getId(), imageDto); + if (images != null) { + imageCount = images.size(); + for (int i = 1; i < imageCount + 1; i++) { + MultipartFile file = images.get(i - 1); + String fileName = postId + "-" + i; + Path filePath = Paths.get(path, fileName); + Files.write(filePath, file.getBytes()); + } } - post.updateImageCount(imageCount); - return post.getId(); + return postId; + } + + public byte[] getImage(Long postId, Long imageId) throws IOException { + String fileName = postId+"-"+imageId; + Path filePath = Paths.get(path, fileName); + return Files.readAllBytes(filePath); } @Transactional @@ -81,23 +95,41 @@ public void updateOnlyPost(Long memberId, Long postId, PostDto postDto){ post.updateOnlyPost(postDto.getTitle(),postDto.getContent(), postDto.getCategory(),postDto.getAnonymous()); } + @Transactional - public void updateOnlyImage(Long memberId, Long postId, List images) throws IOException { + public void updateImageLocal(Long memberId, Long postId, List images) throws IOException{ Post post = postRepository.findById(postId).orElseThrow(()->new MyException(MyErrorCode.POST_NOT_FOUND)); if(!post.getMember().getId().equals(memberId)){ throw new MyException(MyErrorCode.HAS_NOT_POST_AUTHORIZATION); } - redisService.updateImage(postId,images,post.getImageCount()); - post.updateImageCount(images.size()); + if(images!=null){ + for(int i = 1 ; i < post.getImageCount() ; i++){ + String fileName = postId + "-" + i; + Path filePath = Paths.get(path, fileName); + Files.deleteIfExists(filePath); + } + for(int i = 1 ; i < images.size()+1;i++){ + MultipartFile file = images.get(i - 1); + String fileName = postId + "-" + i; + Path filePath = Paths.get(path, fileName); + Files.write(filePath, file.getBytes()); + } + post.updateImageCount(images.size()); + } } @Transactional - public void delete(Long memberId, Long postId){ + public void delete(Long memberId, Long postId) throws IOException { Post post = postRepository.findById(postId).orElseThrow(()->new MyException(MyErrorCode.POST_NOT_FOUND)); - redisService.deleteImage(postId,post.getImageCount()); if(!post.getMember().getId().equals(memberId)){ throw new MyException(MyErrorCode.HAS_NOT_POST_AUTHORIZATION); } + redisService.deleteImage(postId,post.getImageCount()); + for(int i = 1 ; i < post.getImageCount()+1;i++){ + String fileName = postId + "-" + i; + Path filePath = Paths.get(path, fileName); + Files.deleteIfExists(filePath); + } postRepository.delete(post); }