Skip to content

Commit

Permalink
[Feat] 지원서 작성 시 사진 등록 #3 (#42)
Browse files Browse the repository at this point in the history
* feat: 지원서 작성 시 이메일 알림

* feat: 지원서 작성 시 사진 업로드
  • Loading branch information
birdieHyun authored Oct 27, 2023
1 parent 290d648 commit 879e7c0
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 3 deletions.
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ dependencies {

// Email
implementation 'org.springframework.boot:spring-boot-starter-mail'

// aws service
implementation 'com.amazonaws:aws-java-sdk-core:1.12.429'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.429'
implementation 'software.amazon.awssdk:s3:2.16.83'
}

ext {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
package yonseigolf.server.apply.controller;

import net.bytebuddy.utility.RandomString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import yonseigolf.server.apply.dto.request.*;
import yonseigolf.server.apply.dto.response.ApplicationResponse;
import yonseigolf.server.apply.dto.response.ImageResponse;
import yonseigolf.server.apply.dto.response.SingleApplicationResult;
import yonseigolf.server.apply.image.ImageService;
import yonseigolf.server.apply.service.ApplyPeriodService;
import yonseigolf.server.apply.service.ApplyService;
import yonseigolf.server.util.CustomResponse;

import java.time.LocalDate;
import java.time.LocalDateTime;

@Controller
public class ApplicationController {

private final ApplyService applicationService;
private final ApplyPeriodService applyPeriodService;
private final ImageService imageService;

@Autowired
public ApplicationController(ApplyService applicationService, ApplyPeriodService applyPeriodService) {
public ApplicationController(ApplyService applicationService, ApplyPeriodService applyPeriodService, ImageService imageService) {

this.applicationService = applicationService;
this.applyPeriodService = applyPeriodService;
this.imageService = imageService;
}

@PostMapping("/application")
Expand Down Expand Up @@ -211,4 +216,18 @@ public ResponseEntity<CustomResponse> sendFinalFailEmail() {
"연세골프 지원서 최종 불합격자 이메일 전송 성공"
));
}

@PostMapping("/apply/forms/image")
public ResponseEntity<CustomResponse<ImageResponse>> uploadImage(@RequestPart("image") MultipartFile image) {
String imageUrl = imageService.uploadImage(image, RandomString.make(10));

return ResponseEntity
.ok()
.body(new CustomResponse(
"success",
200,
"연세골프 지원서 이미지 업로드 성공",
imageUrl
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package yonseigolf.server.apply.dto.response;

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

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ImageResponse {

private String image;
}
54 changes: 54 additions & 0 deletions src/main/java/yonseigolf/server/apply/image/ImageService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package yonseigolf.server.apply.image;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import java.io.IOException;

@Service
public class ImageService {

private final S3Client s3Client;
@Value("${AWS_S3_BUCKET}")
private String bucketName;

@Autowired
public ImageService(S3Client s3Client) {

this.s3Client = s3Client;
}

public String uploadImage(MultipartFile file, String randomId) {

StringBuilder sb = new StringBuilder();
String fileName = file.getOriginalFilename() + randomId;
String contentType = file.getContentType();

// Upload file
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key("store-image/" + fileName)
.acl("public-read")
.contentDisposition("inline")
.contentType(contentType)
.build();

String url = sb.append("https://")
.append(bucketName)
.append(".s3.ap-northeast-2.amazonaws.com/store-image/")
.append(fileName)
.toString();

try {
s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
return url;
} catch (IOException e) {
throw new IllegalStateException("Failed to upload file", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public ApplyService(ApplicationRepository applicationRepository, EmailRepository
public void apply(ApplicationRequest request) {

applicationRepository.save(Application.of(request));
emailService.sendEmail(request.getEmail(),
"안녕하세요. 연세골프입니다.\n\n",
request.getName() +"님의 지원서가 정상적으로 제출되었습니다. \n\n" +
"서류 합격 여부는 추후 이메일로 공지될 예정입니다. \n\n" +
"감사합니다."
);
}

public void emailAlarm(EmailAlertRequest request) {
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/yonseigolf/server/config/AwsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package yonseigolf.server.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

@Configuration
public class AwsConfig {

@Value("${AWS_ACCESS_KEY}")
private String awsAccessKey;
@Value("${AWS_SECRET_ACCESS_KEY}")
private String awsSecretKey;
@Value("${AWS_REGION}")
private String region;

@Bean
public S3Client s3Client() {
return S3Client.builder()
.region(Region.of(region))
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(awsAccessKey, awsSecretKey)))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import yonseigolf.server.apply.dto.response.ApplicationResponse;
import yonseigolf.server.apply.dto.response.RecruitPeriodResponse;
import yonseigolf.server.apply.dto.response.SingleApplicationResult;
import yonseigolf.server.apply.image.ImageService;
import yonseigolf.server.apply.service.ApplyPeriodService;
import yonseigolf.server.apply.service.ApplyService;
import yonseigolf.server.docs.utils.RestDocsSupport;
Expand Down Expand Up @@ -41,11 +42,13 @@ public class ApplicationControllerTest extends RestDocsSupport {
private ApplyService applyService;
@Mock
private ApplyPeriodService applyPeriodService;
@Mock
private ImageService imageService;

@Override
protected Object initController() {

return new ApplicationController(applyService, applyPeriodService);
return new ApplicationController(applyService, applyPeriodService, imageService);
}

@Test
Expand Down

0 comments on commit 879e7c0

Please sign in to comment.