From 97980460d86bfc9270fef9ffffc24093c5b41582 Mon Sep 17 00:00:00 2001 From: juwum12 Date: Wed, 1 May 2024 18:03:36 +0900 Subject: [PATCH 1/5] =?UTF-8?q?FEAT=20:=20ES=EB=A1=9C=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A0=84=EC=B2=B4=EC=A1=B0=ED=9A=8C=20api=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/dataSources.xml | 18 ---- .../nawabali/config/ElasticSearchConfig.java | 84 +++++++++---------- .../nawabali/controller/PostController.java | 6 ++ .../global/tool/redis/RedisConfig.java | 2 +- .../nawabali/service/PostService.java | 14 +++- 5 files changed, 59 insertions(+), 65 deletions(-) delete mode 100644 .idea/dataSources.xml diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index c3747038..00000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - mysql.8 - true - true - com.mysql.cj.jdbc.Driver - jdbc:mysql://localhost:3306/nawabali - - - - - - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/src/main/java/com/nawabali/nawabali/config/ElasticSearchConfig.java b/src/main/java/com/nawabali/nawabali/config/ElasticSearchConfig.java index 33140f7e..563d1edf 100644 --- a/src/main/java/com/nawabali/nawabali/config/ElasticSearchConfig.java +++ b/src/main/java/com/nawabali/nawabali/config/ElasticSearchConfig.java @@ -1,42 +1,42 @@ -package com.nawabali.nawabali.config; - -import org.elasticsearch.client.RestHighLevelClient; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.RestClients; -import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; -import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; - -@Configuration -@EnableElasticsearchRepositories -public class ElasticSearchConfig extends AbstractElasticsearchConfiguration { - - @Value("${spring.elasticsearch.username}") - private String username; - - @Value("${spring.elasticsearch.password}") - private String password; - - @Value("${spring.elasticsearch.rest.uris}") - private String[] esHost; - - @Override - @Bean - public RestHighLevelClient elasticsearchClient() { - final ClientConfiguration clientConfiguration = ClientConfiguration.builder() - .connectedTo(esHost[0]) - .withBasicAuth(username,password) - .build(); - return RestClients.create(clientConfiguration).rest(); - } - - @Bean - public ElasticsearchOperations elasticsearchOperations(){ - return new ElasticsearchRestTemplate(elasticsearchClient()); - } -} - +//package com.nawabali.nawabali.config; +// +//import org.elasticsearch.client.RestHighLevelClient; +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.data.elasticsearch.client.ClientConfiguration; +//import org.springframework.data.elasticsearch.client.RestClients; +//import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; +//import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +//import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +//import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; +// +//@Configuration +//@EnableElasticsearchRepositories +//public class ElasticSearchConfig extends AbstractElasticsearchConfiguration { +// +// @Value("${spring.elasticsearch.username}") +// private String username; +// +// @Value("${spring.elasticsearch.password}") +// private String password; +// +// @Value("${spring.elasticsearch.rest.uris}") +// private String[] esHost; +// +// @Override +// @Bean +// public RestHighLevelClient elasticsearchClient() { +// final ClientConfiguration clientConfiguration = ClientConfiguration.builder() +// .connectedTo(esHost[0]) +// .withBasicAuth(username,password) +// .build(); +// return RestClients.create(clientConfiguration).rest(); +// } +// +// @Bean +// public ElasticsearchOperations elasticsearchOperations(){ +// return new ElasticsearchRestTemplate(elasticsearchClient()); +// } +//} +// diff --git a/src/main/java/com/nawabali/nawabali/controller/PostController.java b/src/main/java/com/nawabali/nawabali/controller/PostController.java index 0e394ba1..6f591b3c 100644 --- a/src/main/java/com/nawabali/nawabali/controller/PostController.java +++ b/src/main/java/com/nawabali/nawabali/controller/PostController.java @@ -2,6 +2,7 @@ import com.nawabali.nawabali.constant.Category; import com.nawabali.nawabali.constant.Period; +import com.nawabali.nawabali.domain.elasticsearch.PostSearch; import com.nawabali.nawabali.dto.PostDto; import com.nawabali.nawabali.security.UserDetailsImpl; import com.nawabali.nawabali.service.PostService; @@ -68,6 +69,11 @@ public ResponseEntity> getPostsByLatest( return ResponseEntity.ok(postsSlice); } + @GetMapping("/searchAll") + public List searchAll(){ + return postService.searchAllPosts(); + } + // 유저 닉네임으로 그 유저의 게시물들 조회 @Operation( diff --git a/src/main/java/com/nawabali/nawabali/global/tool/redis/RedisConfig.java b/src/main/java/com/nawabali/nawabali/global/tool/redis/RedisConfig.java index b0deaca3..514929cf 100644 --- a/src/main/java/com/nawabali/nawabali/global/tool/redis/RedisConfig.java +++ b/src/main/java/com/nawabali/nawabali/global/tool/redis/RedisConfig.java @@ -31,7 +31,7 @@ public class RedisConfig { public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, redisProperties.getPort()); - config.setPassword(password); +// config.setPassword(password); return new LettuceConnectionFactory(config); // Localhost 전용 diff --git a/src/main/java/com/nawabali/nawabali/service/PostService.java b/src/main/java/com/nawabali/nawabali/service/PostService.java index a7d1b299..d93c2553 100644 --- a/src/main/java/com/nawabali/nawabali/service/PostService.java +++ b/src/main/java/com/nawabali/nawabali/service/PostService.java @@ -17,10 +17,7 @@ import com.nawabali.nawabali.security.UserDetailsImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.SliceImpl; +import org.springframework.data.domain.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -29,6 +26,7 @@ import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import static com.nawabali.nawabali.constant.LikeCategoryEnum.LIKE; import static com.nawabali.nawabali.constant.LikeCategoryEnum.LOCAL_LIKE; @@ -116,6 +114,14 @@ public Slice getPostsByLatest(Pageable pageable) { return new SliceImpl<>(responseDtos, pageable, postSlice.hasNext()); } + // 전체 게시물 조회(지도용) + public List searchAllPosts(){ + Sort sort = Sort.by(Sort.Direction.DESC, "createdAt"); + return StreamSupport.stream( + postSearchRepository.findAll(sort).spliterator(), false) + .toList(); + } + // 상세 게시물 조회 public PostDto.ResponseDetailDto getPost(Long postId, UserDetailsImpl userDetails) { From c3db841961448aafcd63e304882103e10e3566ab Mon Sep 17 00:00:00 2001 From: juwum12 Date: Wed, 1 May 2024 18:04:36 +0900 Subject: [PATCH 2/5] =?UTF-8?q?FEAT=20:=20ES=EB=A1=9C=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A0=84=EC=B2=B4=EC=A1=B0=ED=9A=8C=20api=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a3a0ce1c..98264215 100644 --- a/build.gradle +++ b/build.gradle @@ -30,8 +30,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-cache' // elastic search -// implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch' - implementation 'org.springframework.data:spring-data-elasticsearch:4.2.2' + implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch' +// implementation 'org.springframework.data:spring-data-elasticsearch:4.2.2' // Querydsl 추가 implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' From 18752507a786f8044abacf5b25cfcf135f57145c Mon Sep 17 00:00:00 2001 From: juwum12 Date: Wed, 1 May 2024 23:12:08 +0900 Subject: [PATCH 3/5] =?UTF-8?q?FEAT=20:=20=EC=9D=BC=EA=B4=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20api=EC=B6=94=EA=B0=80,=20es=EB=A1=9C=20=EC=9D=BC?= =?UTF-8?q?=EA=B4=84=EC=A1=B0=ED=9A=8C=20api=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nawabali/config/WebSecurityConfig.java | 2 +- .../nawabali/controller/PostController.java | 7 +- .../com/nawabali/nawabali/domain/Post.java | 3 + .../exception/GlobalExceptionAdvice.java | 2 +- .../nawabali/nawabali/s3/AwsS3Service.java | 20 +++- .../nawabali/security/Jwt/JwtUtil.java | 1 + .../nawabali/service/PostService.java | 98 ++++++++++++++++++- 7 files changed, 125 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/nawabali/nawabali/config/WebSecurityConfig.java b/src/main/java/com/nawabali/nawabali/config/WebSecurityConfig.java index 9f9735e2..ddda92f6 100644 --- a/src/main/java/com/nawabali/nawabali/config/WebSecurityConfig.java +++ b/src/main/java/com/nawabali/nawabali/config/WebSecurityConfig.java @@ -105,7 +105,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers( "/users/logout","/users/signup","/users/check-nickname", "users/info").permitAll() .requestMatchers(HttpMethod.POST, "/users/login").permitAll() - .requestMatchers("/posts","/posts/district/*").permitAll() + .requestMatchers("/posts","/posts/district/*", "posts/searchAll", "posts/updateAll").permitAll() .requestMatchers(HttpMethod.GET, "/posts/**").permitAll() // 게시글 상세 조회 허가 .requestMatchers("/comments/check/posts/**").permitAll() .requestMatchers("/swagger/**","/swagger-ui/**","/v3/api-docs/**").permitAll() diff --git a/src/main/java/com/nawabali/nawabali/controller/PostController.java b/src/main/java/com/nawabali/nawabali/controller/PostController.java index 6f591b3c..9f822bf8 100644 --- a/src/main/java/com/nawabali/nawabali/controller/PostController.java +++ b/src/main/java/com/nawabali/nawabali/controller/PostController.java @@ -68,12 +68,17 @@ public ResponseEntity> getPostsByLatest( Slice postsSlice = postService.getPostsByLatest(pageable); return ResponseEntity.ok(postsSlice); } - + // 전체 게시물 조회(지도용) @GetMapping("/searchAll") public List searchAll(){ return postService.searchAllPosts(); } + @PatchMapping("/updateAll") + public void updateAll() throws IOException { + postService.updateAll(); + } + // 유저 닉네임으로 그 유저의 게시물들 조회 @Operation( diff --git a/src/main/java/com/nawabali/nawabali/domain/Post.java b/src/main/java/com/nawabali/nawabali/domain/Post.java index 3007841b..b19a414c 100644 --- a/src/main/java/com/nawabali/nawabali/domain/Post.java +++ b/src/main/java/com/nawabali/nawabali/domain/Post.java @@ -68,4 +68,7 @@ public void update(String contents) { } + public void updateImages(List existsImages) { + this.images = existsImages; + } } diff --git a/src/main/java/com/nawabali/nawabali/exception/GlobalExceptionAdvice.java b/src/main/java/com/nawabali/nawabali/exception/GlobalExceptionAdvice.java index 9832156b..796f121a 100644 --- a/src/main/java/com/nawabali/nawabali/exception/GlobalExceptionAdvice.java +++ b/src/main/java/com/nawabali/nawabali/exception/GlobalExceptionAdvice.java @@ -135,7 +135,7 @@ public class GlobalExceptionAdvice { @Value("${error.detailed-messages}") private boolean detailedMessages; - // CustomException: Error Code에 정의된 비즈니스 로직 오류 +// CustomException: Error Code에 정의된 비즈니스 로직 오류 // @ExceptionHandler(CustomException.class) // public ResponseEntity handleCustomException(CustomException e) { // diff --git a/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java b/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java index 4e7647c9..2d3071ed 100644 --- a/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java +++ b/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java @@ -1,10 +1,7 @@ package com.nawabali.nawabali.s3; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.*; import com.nawabali.nawabali.exception.CustomException; import com.nawabali.nawabali.exception.ErrorCode; import lombok.RequiredArgsConstructor; @@ -113,4 +110,19 @@ public String uploadSingleFile(MultipartFile multipartFile, String dirName){ throw new CustomException(ErrorCode.PHOTO_UPLOAD_ERROR); } } + + public S3Object getS3Object(String objectKey){ + return amazonS3.getObject(bucket, objectKey); + } + + public String getContentType(String objectKey){ + S3Object s3Object = amazonS3.getObject(bucket, objectKey); + return s3Object.getObjectMetadata().getContentType(); + } + + public String saveAndGetUrl(String resizedFilePath, S3ObjectInputStream inputStream, ObjectMetadata resizedMetadata){ + amazonS3.putObject(new PutObjectRequest(bucket, resizedFilePath, inputStream, resizedMetadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + return amazonS3.getUrl(bucket, resizedFilePath).toString(); + } } diff --git a/src/main/java/com/nawabali/nawabali/security/Jwt/JwtUtil.java b/src/main/java/com/nawabali/nawabali/security/Jwt/JwtUtil.java index a49c27bd..3b792a45 100644 --- a/src/main/java/com/nawabali/nawabali/security/Jwt/JwtUtil.java +++ b/src/main/java/com/nawabali/nawabali/security/Jwt/JwtUtil.java @@ -16,6 +16,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseCookie; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; diff --git a/src/main/java/com/nawabali/nawabali/service/PostService.java b/src/main/java/com/nawabali/nawabali/service/PostService.java index d93c2553..bfd4ab89 100644 --- a/src/main/java/com/nawabali/nawabali/service/PostService.java +++ b/src/main/java/com/nawabali/nawabali/service/PostService.java @@ -1,5 +1,7 @@ package com.nawabali.nawabali.service; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.*; import com.nawabali.nawabali.constant.*; import com.nawabali.nawabali.domain.BookMark; import com.nawabali.nawabali.domain.Like; @@ -17,12 +19,18 @@ import com.nawabali.nawabali.security.UserDetailsImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import net.coobird.thumbnailator.Thumbnails; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -32,7 +40,7 @@ import static com.nawabali.nawabali.constant.LikeCategoryEnum.LOCAL_LIKE; @Service -@Slf4j +@Slf4j(topic = "PostService") @RequiredArgsConstructor @Transactional(readOnly = true) public class PostService { @@ -45,6 +53,9 @@ public class PostService { private final PostSearchRepository postSearchRepository; private final ProfileImageRepository profileImageRepository; private final BookMarkRepository bookMarkRepository; + private final AmazonS3 amazonS3; + @Value("${cloud.aws.s3.bucket}") + private String bucket; // 게시물 생성 @@ -204,6 +215,91 @@ public List getCategoryByPost(String district) { return postRepository.findCategoryByPost(district); } + @Transactional + public void updateAll() throws IOException{ + Sort sort = Sort.by(Sort.Direction.ASC, "createdAt"); + List allPosts = postRepository.findAll(sort); + + for(Post post : allPosts){ + Long postId = post.getId(); + List existImages = post.getImages(); + log.info("기존 이미지 사진 갯수 :" + existImages.size()); + PostImage firstPostImage = existImages.get(0); + String firstImageUrl = firstPostImage.getImgUrl(); + //URL 파싱하여 S3의 이미지 로드 + String dirName = "postImages/"; + String objectKey = getObjectKeyFromUrl(dirName, firstImageUrl); + log.info("objectKey : " + objectKey); + String contentType = awsS3Service.getContentType(objectKey); + log.info(contentType); + + S3Object s3Object = awsS3Service.getS3Object(objectKey); + try(S3ObjectInputStream inputStream = s3Object.getObjectContent()){ + //로드된 이미지 리사이즈 로직 통과 s3저장 후 빌더로 PostImage 객체 생성 + //1.로드된 이미지 리사이징 + log.info("게시글 번호 : " + postId + " 리사이징 진행"); + + ByteArrayOutputStream resizedOs = new ByteArrayOutputStream(); + Thumbnails.of(inputStream) + .size(60,60) + .outputQuality(0.75) + .toOutputStream(resizedOs); +// log.info("ByteArrayOutputStream : " + resizedOs); + log.info("게시글 번호 : " + postId + " 리사이징 완료"); + + //2.s3저장 + log.info("게시글 번호 : " +postId + " s3 저장 시작"); + byte[] resizedImageBytes = resizedOs.toByteArray(); + log.info("resizedImageBytes : "+ resizedImageBytes.length); + long contentLength = resizedImageBytes.length; + String resizedFilePath = "compressed_postImages/" + firstImageUrl; + log.info("resizedFilePath : " + resizedFilePath); + ObjectMetadata resizedMetadata = new ObjectMetadata(); + resizedMetadata.setContentLength(contentLength); + resizedMetadata.setContentType(contentType); + log.info("이미지 저장시작"); + amazonS3.putObject(new PutObjectRequest(bucket, resizedFilePath, inputStream, resizedMetadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + + + String resizedImageUrl = awsS3Service.saveAndGetUrl(resizedFilePath, inputStream, resizedMetadata); + log.info("S3저장완료. 저장된 이미지 주소 : " + resizedImageUrl); + + + //3.PostImage 객체 생성 후 리스트에 추가 + PostImage resizedImage = PostImage.builder() + .fileName(resizedImageUrl) + .imgUrl(resizedImageUrl) + .post(post) + .build(); + + existImages.add(0, resizedImage); + post.updateImages(existImages); + log.info("추가 후 이미지 사진 갯수 : " + existImages.size()); + + //4.ES에 저장 + User writer = post.getUser(); + List existImagesUrls = existImages.stream().map(PostImage::getImgUrl).toList(); + PostSearch postSearch = createPostSearch(post, existImagesUrls, writer); + postSearchRepository.save(postSearch); + log.info("Document PK : " + postSearch.getId()); + log.info("게시글 PK : "+ postSearch.getPostId()); + + } + + } + } + + private String getObjectKeyFromUrl(String dirName, String imageUrl) { + // URL에서 마지막 슬래시('/') 이후의 부분을 객체 키로 반환합니다. + int lastSlashIndex = imageUrl.lastIndexOf('/'); + if (lastSlashIndex != -1 && lastSlashIndex < imageUrl.length() - 1) { + return dirName + imageUrl.substring(lastSlashIndex + 1); + } else { + throw new IllegalArgumentException("Invalid S3 URL: " + imageUrl); + } + } + // 게시물 수정 - 사용자 신원 확인 @Transactional public PostDto.PatchDto updatePost(Long postId, User user, PostDto.PatchDto patchDto) { From f4d38e322aacc62e5d4f1227dcb05d83a3281df4 Mon Sep 17 00:00:00 2001 From: juwum12 Date: Thu, 2 May 2024 03:53:02 +0900 Subject: [PATCH 4/5] =?UTF-8?q?FEAT=20:=20Es=20=EC=BB=AC=EB=9F=BC=EC=97=90?= =?UTF-8?q?=20resizedImageUrl=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nawabali/controller/PostController.java | 3 ++ .../domain/elasticsearch/PostSearch.java | 3 ++ .../nawabali/nawabali/s3/AwsS3Service.java | 2 +- .../nawabali/service/PostService.java | 45 +++++++++++-------- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/nawabali/nawabali/controller/PostController.java b/src/main/java/com/nawabali/nawabali/controller/PostController.java index 9f822bf8..3320d543 100644 --- a/src/main/java/com/nawabali/nawabali/controller/PostController.java +++ b/src/main/java/com/nawabali/nawabali/controller/PostController.java @@ -69,6 +69,9 @@ public ResponseEntity> getPostsByLatest( return ResponseEntity.ok(postsSlice); } // 전체 게시물 조회(지도용) + @Operation( + summary = "전체 게시글 조회", + description = "ES로 전체 조회, 등록일 기준 내림차순 정렬") @GetMapping("/searchAll") public List searchAll(){ return postService.searchAllPosts(); diff --git a/src/main/java/com/nawabali/nawabali/domain/elasticsearch/PostSearch.java b/src/main/java/com/nawabali/nawabali/domain/elasticsearch/PostSearch.java index 255f9acc..89ccd736 100644 --- a/src/main/java/com/nawabali/nawabali/domain/elasticsearch/PostSearch.java +++ b/src/main/java/com/nawabali/nawabali/domain/elasticsearch/PostSearch.java @@ -62,6 +62,9 @@ public class PostSearch { @Field(type = FieldType.Keyword) private String mainImageUrl; + @Field(type=FieldType.Keyword) + private String resizedImageUrl; + @Field(type = FieldType.Boolean) private boolean multiImages; diff --git a/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java b/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java index 2d3071ed..87da86ed 100644 --- a/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java +++ b/src/main/java/com/nawabali/nawabali/s3/AwsS3Service.java @@ -120,7 +120,7 @@ public String getContentType(String objectKey){ return s3Object.getObjectMetadata().getContentType(); } - public String saveAndGetUrl(String resizedFilePath, S3ObjectInputStream inputStream, ObjectMetadata resizedMetadata){ + public String saveAndGetUrl(String resizedFilePath, ByteArrayInputStream inputStream, ObjectMetadata resizedMetadata){ amazonS3.putObject(new PutObjectRequest(bucket, resizedFilePath, inputStream, resizedMetadata) .withCannedAcl(CannedAccessControlList.PublicRead)); return amazonS3.getUrl(bucket, resizedFilePath).toString(); diff --git a/src/main/java/com/nawabali/nawabali/service/PostService.java b/src/main/java/com/nawabali/nawabali/service/PostService.java index bfd4ab89..093c2f45 100644 --- a/src/main/java/com/nawabali/nawabali/service/PostService.java +++ b/src/main/java/com/nawabali/nawabali/service/PostService.java @@ -1,7 +1,9 @@ package com.nawabali.nawabali.service; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.*; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.S3Object; +import com.amazonaws.services.s3.model.S3ObjectInputStream; import com.nawabali.nawabali.constant.*; import com.nawabali.nawabali.domain.BookMark; import com.nawabali.nawabali.domain.Like; @@ -26,13 +28,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; import java.time.LocalDateTime; -import java.util.*; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -103,7 +105,7 @@ public PostDto.ResponseDto createPost(User user, PostDto.RequestDto requestDto, }); Post savedPost = postRepository.save(post); - PostSearch postSearch = createPostSearch(savedPost, originalUrls, findUser); + PostSearch postSearch = createPostSearch(savedPost, originalUrls, resizedImageUrl, findUser); postSearchRepository.save(postSearch); User userUp = post.getUser(); @@ -231,38 +233,43 @@ public void updateAll() throws IOException{ String objectKey = getObjectKeyFromUrl(dirName, firstImageUrl); log.info("objectKey : " + objectKey); String contentType = awsS3Service.getContentType(objectKey); - log.info(contentType); + log.info("contentType : " + contentType); S3Object s3Object = awsS3Service.getS3Object(objectKey); try(S3ObjectInputStream inputStream = s3Object.getObjectContent()){ + byte[] bytes = inputStream.readAllBytes(); + //로드된 이미지 리사이즈 로직 통과 s3저장 후 빌더로 PostImage 객체 생성 //1.로드된 이미지 리사이징 log.info("게시글 번호 : " + postId + " 리사이징 진행"); - + InputStream compressedInputStream = new ByteArrayInputStream(bytes); ByteArrayOutputStream resizedOs = new ByteArrayOutputStream(); - Thumbnails.of(inputStream) + Thumbnails.of(compressedInputStream) .size(60,60) .outputQuality(0.75) .toOutputStream(resizedOs); + byte[] compressedImage = resizedOs.toByteArray(); // log.info("ByteArrayOutputStream : " + resizedOs); log.info("게시글 번호 : " + postId + " 리사이징 완료"); //2.s3저장 log.info("게시글 번호 : " +postId + " s3 저장 시작"); - byte[] resizedImageBytes = resizedOs.toByteArray(); - log.info("resizedImageBytes : "+ resizedImageBytes.length); - long contentLength = resizedImageBytes.length; - String resizedFilePath = "compressed_postImages/" + firstImageUrl; - log.info("resizedFilePath : " + resizedFilePath); + + ByteArrayInputStream uploadInputStream = new ByteArrayInputStream(compressedImage); + + long contentLength = compressedImage.length; + String compressedFilePath = "compressed_" + objectKey; + log.info("compressedFilePath : " + compressedFilePath); + ObjectMetadata resizedMetadata = new ObjectMetadata(); resizedMetadata.setContentLength(contentLength); resizedMetadata.setContentType(contentType); log.info("이미지 저장시작"); - amazonS3.putObject(new PutObjectRequest(bucket, resizedFilePath, inputStream, resizedMetadata) - .withCannedAcl(CannedAccessControlList.PublicRead)); + log.info(s3Object.getKey()); + - String resizedImageUrl = awsS3Service.saveAndGetUrl(resizedFilePath, inputStream, resizedMetadata); + String resizedImageUrl = awsS3Service.saveAndGetUrl(compressedFilePath, uploadInputStream, resizedMetadata); log.info("S3저장완료. 저장된 이미지 주소 : " + resizedImageUrl); @@ -273,14 +280,13 @@ public void updateAll() throws IOException{ .post(post) .build(); - existImages.add(0, resizedImage); post.updateImages(existImages); log.info("추가 후 이미지 사진 갯수 : " + existImages.size()); //4.ES에 저장 User writer = post.getUser(); List existImagesUrls = existImages.stream().map(PostImage::getImgUrl).toList(); - PostSearch postSearch = createPostSearch(post, existImagesUrls, writer); + PostSearch postSearch = createPostSearch(post, existImagesUrls, resizedImageUrl, writer); postSearchRepository.save(postSearch); log.info("Document PK : " + postSearch.getId()); log.info("게시글 PK : "+ postSearch.getPostId()); @@ -460,7 +466,7 @@ private PostDto.ResponseDto convertToResponseDto(PostDto.ResponseDto post) { } - private PostSearch createPostSearch(Post post, List imageUrls, User user) { + private PostSearch createPostSearch(Post post, List imageUrls, String resizedImageUrl, User user) { PostSearch postSearch = new PostSearch(); postSearch.setId(post.getId().toString()); @@ -479,6 +485,7 @@ private PostSearch createPostSearch(Post post, List imageUrls, User user postSearch.setModifiedAt(post.getModifiedAt()); postSearch.setMainImageUrl(imageUrls.isEmpty() ? null : imageUrls.get(0)); postSearch.setMultiImages(imageUrls.size() > 1); + postSearch.setResizedImageUrl(resizedImageUrl); postSearch.setLikesCount(0L); postSearch.setLocalLikesCount(0L); postSearch.setCommentCount(0); From e2e0bb840fc81d802a7f80a44524dfd8ec2f7c7f Mon Sep 17 00:00:00 2001 From: juwum12 Date: Thu, 2 May 2024 11:25:52 +0900 Subject: [PATCH 5/5] Develop Merging --- .idea/dataSources.xml | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 04f8474e..242453ce 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -1,9 +1,10 @@ - + mysql.8 true + true com.mysql.cj.jdbc.Driver jdbc:mysql://localhost:3306/nawabali @@ -13,29 +14,5 @@ $ProjectFileDir$ - - mysql.8 - true - com.mysql.cj.jdbc.Driver - jdbc:mysql://springboot-database.cbe6ouewo4p0.ap-northeast-2.rds.amazonaws.com:3306/sparta - - - - - - $ProjectFileDir$ - - - mysql.8 - true - com.mysql.cj.jdbc.Driver - jdbc:mysql://db-dongnaebangnae.cbe6ouewo4p0.ap-northeast-2.rds.amazonaws.com:3306/sparta - - - - - - $ProjectFileDir$ - \ No newline at end of file