Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:

# 3. 최신 이미지를 컨테이너화하여 실행
- name: docker run new container
run: sudo docker run --name helfoome --rm -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKERHUB_USERNAME }}/team01
run: sudo docker run --name team01 --rm -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKERHUB_USERNAME }}/team01

# 4. 미사용 이미지를 정리
- name: delete old docker image
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# JDK21
FROM openjdk:21
# JDK17
FROM openjdk:17

# 인자 설정, jar 파일 복제
COPY build/libs/*.jar app.jar

# 실행 명령어
ENTRYPOINT ["java", "-jar", "app.jar"]
ENTRYPOINT ["java", "-jar", "app.jar"]
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ dependencies {
compileOnly 'org.projectlombok:lombok'

// DB
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/uggthon/team01/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.uggthon.team01.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;

@Configuration
public class S3Config {

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

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

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

@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client)
AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
4 changes: 2 additions & 2 deletions src/main/java/com/uggthon/team01/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

// Swagger 접속 주소
// http://localhost:8080/swagger-ui/index.html#/
// https://{ip-address}:8080/swagger-ui/index.html
// https://13.60.193.191:8080/swagger-ui/index.html

@Configuration
public class SwaggerConfig {
Expand All @@ -26,7 +26,7 @@ public OpenAPI customOpenAPI() {
localServer.setDescription("Local Server");

Server prodServer = new Server();
prodServer.setUrl("https://16.171.3.150:8080/swagger-ui/index.html");
prodServer.setUrl("http://13.60.193.191:8080/swagger-ui/index.html");
prodServer.setDescription("Production Server");

return new OpenAPI()
Expand Down
111 changes: 111 additions & 0 deletions src/main/java/com/uggthon/team01/service/S3Service.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.uggthon.team01.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;

import lombok.extern.slf4j.Slf4j;

// 이 서비스는 데베에 저장하는 서비스 X
// S3에 실제 파일을 업로드 (이름 겹치치 않게 파일이름 = 날짜-파일이름 으로 변경해서 올리는 기능)
// 이미지를 업로드할 일이 생기면 본인 서비스에서 요기 함수 호출해서 s3에 파일 업로드하고
// 파일 경로랑 원본 파일명은 호출한 서비스에서 따로 저장해주셔야됭미

@Slf4j
@Service
public class S3Service {

private final AmazonS3 s3Client;

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

public S3Service(
@Value("${aws.credentials.access-key}") String accessKey,
@Value("${aws.credentials.secret-key}") String secretKey,
@Value("${aws.region}") String region) {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
this.s3Client =
AmazonS3ClientBuilder.standard()
.withRegion(Regions.fromName(region))
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
}

// dirName은 S3의 어떤 폴더인지 같이 넣어주면 됨 예를들면 profileImage.. shopImage.....etc
public String upload(MultipartFile multipartFile, String dirName) throws IOException {
String originalFileName = multipartFile.getOriginalFilename();
String uuid = UUID.randomUUID().toString();
String uniqueFileName = uuid + "_" + originalFileName.replaceAll("\\s", "_");

String fileName = dirName + "/" + uniqueFileName;
log.info("fileName: " + fileName);

File uploadFile = convert(multipartFile);
String uploadImageUrl = putS3(uploadFile, fileName);
removeNewFile(uploadFile);
return uploadImageUrl;
}

private 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 convertFile;
}
throw new IllegalArgumentException("파일 변환에 실패했습니다: " + file.getOriginalFilename());
}

private String putS3(File uploadFile, String fileName) {
s3Client.putObject(
new PutObjectRequest(bucketName, fileName, uploadFile)
.withCannedAcl(CannedAccessControlList.PublicRead));
return s3Client.getUrl(bucketName, fileName).toString();
}

// 전환할 때 임시파일이 생성돼서 삭제해야함
private void removeNewFile(File targetFile) {
if (targetFile.delete()) {
log.info("파일이 삭제되었습니다.");
} else {
log.info("파일이 삭제되지 못했습니다.");
}
}

public void deleteFile(String fileName) {
try {
// URL 디코딩을 통해 원래의 파일 이름을 가져옴
String decodedFileName = URLDecoder.decode(fileName, "UTF-8");
log.info("Deleting file from S3: " + decodedFileName);
s3Client.deleteObject(bucketName, decodedFileName);
} catch (UnsupportedEncodingException e) {
log.error("Error while decoding the file name: {}", e.getMessage());
}
}

public String updateFile(MultipartFile newFile, String oldFileName, String dirName)
throws IOException {
// 기존 파일 삭제
log.info("S3 oldFileName: " + oldFileName);
deleteFile(oldFileName);
// 새 파일 업로드
return upload(newFile, dirName);
}
}
Loading