Skip to content

Commit

Permalink
Merge pull request #49 from UMC-HACKATHON-SnapSpot/feat/#46
Browse files Browse the repository at this point in the history
[feat] s3 사진 등록
  • Loading branch information
do-dop authored Jul 4, 2024
2 parents 29d1ad0 + 3732acd commit 2aa313d
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 7 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,6 @@ gradle-app.setting

# End of https://www.toptal.com/developers/gitignore/api/java,intellij+all,gradle

.env
.env

src/main/resources/application-secret.yml
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
implementation 'org.springframework.security:spring-security-crypto'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' // AWS
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.h2database:h2'
Expand Down
39 changes: 39 additions & 0 deletions src/main/java/com/umc/hackaton/snapspot/S3/S3Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.umc.hackaton.snapspot.S3;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/api/v1/s3")
@RequiredArgsConstructor
@Slf4j
public class S3Controller {

private final S3Service s3Service;

@PostMapping("/upload")
public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) {
try {
String fileUrl = s3Service.saveFile(file);
return ResponseEntity.ok(fileUrl);
} catch (Exception e) {
log.error(e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("S3 업로드에 실패했습니다.");
}
}

@GetMapping("/file")
public ResponseEntity<?> getFile(@RequestParam("fileName") String fileName) {
try {
String fileUrl = s3Service.getFile(fileName);
return ResponseEntity.ok(fileUrl);
} catch (Exception e) {
log.error(e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("S3 파일 조회에 실패했습니다.");
}
}
}
64 changes: 64 additions & 0 deletions src/main/java/com/umc/hackaton/snapspot/S3/S3Service.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.umc.hackaton.snapspot.S3;


import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
@Slf4j
@RequiredArgsConstructor
public class S3Service {

private final AmazonS3 amazonS3Client;

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

@Transactional
public String saveFile(MultipartFile multipartFile) {

String originalFilename = multipartFile.getOriginalFilename();
try {

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(multipartFile.getSize());
metadata.setContentType(multipartFile.getContentType());

amazonS3Client.putObject(new PutObjectRequest(bucket, originalFilename, multipartFile.getInputStream(), metadata));
return amazonS3Client.getUrl(bucket, originalFilename).toString();
} catch (IOException e) {
// 파일 입출력 예외 처리
e.printStackTrace();
return "File upload failed due to an IO error: " + e.getMessage();
} catch (AmazonS3Exception e) {
// AWS S3 관련 예외 처리
e.printStackTrace();
return "File upload failed due to an Amazon S3 error: " + e.getMessage();
} catch (SdkClientException e) {
// AWS SDK 관련 클라이언트 예외 처리
e.printStackTrace();
return "File upload failed due to an SDK client error: " + e.getMessage();
} catch (Exception e) {
// 기타 모든 예외 처리
e.printStackTrace();
return "File upload failed due to an unexpected error: " + e.getMessage();
}
}
@Transactional
public String getFile(String fileName) {
return amazonS3Client.getUrl(bucket, fileName).toString();


}
}
36 changes: 36 additions & 0 deletions src/main/java/com/umc/hackaton/snapspot/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.umc.hackaton.snapspot.config;


import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class S3Config {

@Value("${cloud.aws.credentials.access-key}")
private String accessKey;

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

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

@Bean
public AmazonS3 amazonS3() {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);

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

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

Expand All @@ -23,9 +24,9 @@ public class SpotController {
private final SpotService spotService;

@PostMapping
public ResponseEntity<?> upload(@RequestBody SpotRequestDto dto) {
public ResponseEntity<?> upload(@RequestPart(value = "file") MultipartFile file, @RequestPart SpotRequestDto dto) {
try {
Spot spot = spotService.upload(dto);
Spot spot = spotService.upload(dto, file);
return ResponseEntity.ok().body(spot);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("스팟 업로드에 실패하였습니다.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public class SpotRequestDto {
private Double longitude;
private String title;
private String description;
private String imgUrl;
private List<Long> categoryNums;

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void decreaseLike() {

public Spot update(SpotRequestDto dto){
this.description = dto.getDescription();
this.imgUrl = dto.getImgUrl();;
// this.imgUrl = dto.getImgUrl();;
this.title = dto.getTitle();
return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.umc.hackaton.snapspot.spot.service;

import com.umc.hackaton.snapspot.S3.S3Service;
import com.umc.hackaton.snapspot.category.entity.Category;
import com.umc.hackaton.snapspot.category.entity.CategorySpot;
import com.umc.hackaton.snapspot.category.repository.CategoryRepository;
Expand All @@ -14,7 +15,10 @@
import com.umc.hackaton.snapspot.user.repository.UserRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -23,13 +27,18 @@
@Service
@RequiredArgsConstructor
public class SpotService {
private static final Logger log = LoggerFactory.getLogger(SpotService.class);
private final SpotRepository spotRepository;
private final UserRepository userRepository;
private final CategoryRepository categoryRepository;
private final CategorySpotRepository categorySpotRepository;
private final S3Service s3Service;

@Transactional
public Spot upload(SpotRequestDto dto) {
public Spot upload(SpotRequestDto dto, MultipartFile file) {

String imgUrl = s3Service.saveFile(file);
log.info("imgUrl: " + imgUrl);

User user = userRepository.findUserById(dto.getUserId());

Expand All @@ -39,7 +48,7 @@ public Spot upload(SpotRequestDto dto) {
spotDto.setLatitude(dto.getLatitude());
spotDto.setTitle(dto.getTitle());
spotDto.setDescription(dto.getDescription());
spotDto.setImgUrl(dto.getImgUrl());
spotDto.setImgUrl(imgUrl);

Spot savedSpot = spotRepository.save(spotDto.toEntity());

Expand All @@ -60,6 +69,8 @@ public Spot upload(SpotRequestDto dto) {
return savedSpot;
}



@Transactional
public Spot getSpotById(Long spotId) {
// spotId를 사용하여 Repository를 통해 Spot을 가져옴
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
spring:
profiles:
active:
- secret
datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/spot?useSSL=false&allowPublicKeyRetrieval=true
Expand Down

0 comments on commit 2aa313d

Please sign in to comment.