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 : s3설정, 이미지 업로드 api 추가 #46

Merged
merged 1 commit into from
Aug 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
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.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/hsu/umc/server/aws/s3/AmazonS3Manager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package hsu.umc.server.aws.s3;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import hsu.umc.server.config.AmazonConfig;
import hsu.umc.server.entity.Uuid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Slf4j
@Component
@RequiredArgsConstructor
public class AmazonS3Manager {
private final AmazonS3 amazonS3;
private final AmazonConfig amazonConfig;
public String uploadFile(String keyName, MultipartFile file)throws IOException {
System.out.println(keyName);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());
amazonS3.putObject(new PutObjectRequest(amazonConfig.getBucket(), keyName, file.getInputStream(), metadata));
return amazonS3.getUrl(amazonConfig.getBucket(),keyName).toString();
}
public String generatePhotoKeyName(Uuid uuid) {
return amazonConfig.getPhotoPath() + '/' + uuid.getUuid();
}
}
51 changes: 51 additions & 0 deletions src/main/java/hsu/umc/server/config/AmazonConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package hsu.umc.server.config;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Getter
public class AmazonConfig {

private AWSCredentials awsCredentials;

@Value("${cloud.aws.credentials.accessKey}")
private String accesskey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Value("${cloud.aws.s3.bucket}")
private String bucket;


@Value("${cloud.aws.s3.path.photo}")
private String photoPath;

@PostConstruct
public void init(){
this.awsCredentials = new BasicAWSCredentials(accesskey, secretKey);
}
@Bean
public AmazonS3 amazonS3() {
AWSCredentials awsCredentials = new BasicAWSCredentials(accesskey, secretKey);
return AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}

@Bean
public AWSCredentialsProvider awsCredentialsProvider(){
return new AWSStaticCredentialsProvider(awsCredentials);
}
}
12 changes: 12 additions & 0 deletions src/main/java/hsu/umc/server/converter/PhotoConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hsu.umc.server.converter;

import hsu.umc.server.entity.Photo;
import hsu.umc.server.web.dto.PhotoResponseDto;

public class PhotoConverter {
public static PhotoResponseDto.CreatePhotoResultDto toCreatePhotoResultDto(Photo photo){
return PhotoResponseDto.CreatePhotoResultDto.builder()
.photoUrl(photo.getPhotoUrl())
.build();
}
}
20 changes: 20 additions & 0 deletions src/main/java/hsu/umc/server/entity/Photo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package hsu.umc.server.entity;


import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;

@Entity
@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Photo extends BaseEntity {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String photoUrl;

}
16 changes: 16 additions & 0 deletions src/main/java/hsu/umc/server/entity/Uuid.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package hsu.umc.server.entity;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Uuid extends BaseEntity{
@Id @GeneratedValue(strategy = GenerationType.IDENTITY )
private Long id;
@Column(unique = true)
private String uuid;
}
7 changes: 7 additions & 0 deletions src/main/java/hsu/umc/server/repository/PhotoRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package hsu.umc.server.repository;

import hsu.umc.server.entity.Photo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PhotoRepository extends JpaRepository<Photo, Long> {
}
7 changes: 7 additions & 0 deletions src/main/java/hsu/umc/server/repository/UuidRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package hsu.umc.server.repository;

import hsu.umc.server.entity.Uuid;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UuidRepository extends JpaRepository<Uuid, Long> {
}
9 changes: 9 additions & 0 deletions src/main/java/hsu/umc/server/service/PhotoCommandService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package hsu.umc.server.service;

import hsu.umc.server.entity.Photo;
import org.springframework.web.multipart.MultipartFile;


public interface PhotoCommandService {
Photo createPhoto(MultipartFile request);
}
41 changes: 41 additions & 0 deletions src/main/java/hsu/umc/server/service/PhotoCommandServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package hsu.umc.server.service;

import hsu.umc.server.aws.s3.AmazonS3Manager;
import hsu.umc.server.entity.Photo;
import hsu.umc.server.entity.Uuid;
import hsu.umc.server.repository.PhotoRepository;
import hsu.umc.server.repository.UuidRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class PhotoCommandServiceImpl implements PhotoCommandService{
private final AmazonS3Manager s3Manager;
private final UuidRepository uuidRepository;
private final PhotoRepository photoRepository;
@Override
@Transactional
public Photo createPhoto(MultipartFile photoPicture) {
String uuid = UUID.randomUUID().toString();
Uuid savedUuid = uuidRepository.save(Uuid.builder().uuid(uuid).build());
String pictureUrl = null;
try {
pictureUrl = s3Manager.uploadFile(s3Manager.generatePhotoKeyName(savedUuid), photoPicture);
} catch (IOException e) {
throw new RuntimeException(e);
}

Photo photo = Photo.builder()
.photoUrl(pictureUrl)
.build();

return photoRepository.save(photo);
}
}
29 changes: 29 additions & 0 deletions src/main/java/hsu/umc/server/web/controller/PhotoController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package hsu.umc.server.web.controller;

import hsu.umc.server.apipayload.ApiResponse;
import hsu.umc.server.converter.PhotoConverter;
import hsu.umc.server.entity.Photo;
import hsu.umc.server.service.PhotoCommandService;
import hsu.umc.server.web.dto.PhotoResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;


@RestController
@RequestMapping("/api/photo")
@RequiredArgsConstructor
@Tag(name="photo",description = "네컷사진 관련 API")
public class PhotoController {
private final PhotoCommandService photoCommandService;
@PostMapping(value = "/",consumes = "multipart/form-data")
@Operation(summary = "네컷 사진 저장", description = "제공된 사진을 저장하고 url을 반환합니다.")
public ApiResponse<PhotoResponseDto.CreatePhotoResultDto> createPhoto(
@RequestPart("photoPicture") MultipartFile photoPicture) {
Photo photo = photoCommandService.createPhoto(photoPicture);
return ApiResponse.onSuccess(PhotoConverter.toCreatePhotoResultDto(photo));
}

}
16 changes: 16 additions & 0 deletions src/main/java/hsu/umc/server/web/dto/PhotoResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package hsu.umc.server.web.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

public class PhotoResponseDto {
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class CreatePhotoResultDto{
private String photoUrl;
}
}
14 changes: 14 additions & 0 deletions src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,17 @@ spring:
allowed-headers: "*"
allow-credentials: true

cloud:
aws:
s3:
bucket: umc-7th
path:
photo : photos
region:
static: ap-northeast-2
stack:
auto: false
credentials:
accessKey: ${aws.access.key.id}
secretKey: ${aws.secret.access.key}

16 changes: 15 additions & 1 deletion src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,18 @@ spring:
format_sql: true
use_sql_comments: true
hbm2ddl:
auto: update
auto: update

cloud:
aws:
s3:
bucket: umc-7th
path:
photo : photos
region:
static: ap-northeast-2
stack:
auto: false
credentials:
accessKey: ${aws.access.key.id}
secretKey: ${aws.secret.access.key}
Loading