Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.wandering.Do.domain.image.presentation;

import com.wandering.Do.domain.image.presentation.dto.res.ImageUploadRes;
import com.wandering.Do.domain.image.service.ImageUploadService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequiredArgsConstructor
@RequestMapping("/my")
public class ImageController {

private final ImageUploadService imageUploadService;

@PostMapping
public ResponseEntity<ImageUploadRes> upload(@RequestPart MultipartFile image) {
ImageUploadRes response = imageUploadService.execute(image);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.wandering.Do.domain.image.presentation.dto.res;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ImageUploadRes {
private String url;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.wandering.Do.domain.image.service;

import com.wandering.Do.domain.image.presentation.dto.res.ImageUploadRes;
import org.springframework.web.multipart.MultipartFile;

public interface ImageUploadService {
ImageUploadRes execute(MultipartFile image);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.wandering.Do.domain.image.service.impl;

import com.wandering.Do.domain.image.presentation.dto.res.ImageUploadRes;
import com.wandering.Do.domain.image.service.ImageUploadService;
import com.wandering.Do.domain.image.util.ImageConverter;
import com.wandering.Do.global.annotation.ServiceWithTransactional;
import com.wandering.Do.global.s3.S3Util;
import lombok.RequiredArgsConstructor;
import org.springframework.web.multipart.MultipartFile;

@ServiceWithTransactional
@RequiredArgsConstructor
public class ImageUploadServiceImpl implements ImageUploadService {

private final S3Util s3Util;
private final ImageConverter imageConverter;

public ImageUploadRes execute(MultipartFile image) {

String img_url = s3Util.imageUpload(image);
return imageConverter.toDto(img_url);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.wandering.Do.domain.image.util;

import com.wandering.Do.domain.image.presentation.dto.res.ImageUploadRes;

public interface ImageConverter {
ImageUploadRes toDto(String url);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.wandering.Do.domain.image.util.impl;

import com.wandering.Do.domain.image.presentation.dto.res.ImageUploadRes;
import com.wandering.Do.domain.image.util.ImageConverter;
import org.springframework.stereotype.Component;

@Component
public class ImageConverterImpl implements ImageConverter {
@Override
public ImageUploadRes toDto(String url) {
return ImageUploadRes.builder()
.url(url)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public enum ErrorCode {
USER_NOT_MATCH(403, "이 글에 대한 접근 권한이 없습니다."),
NOT_INCLUDED_APPLICATION(403, "해당 유저는 약속을 신청하지 않았습니다"),


//promise
PROMISE_NOT_FOUND(404, "해당 글을 찾을 수 없습니다"),
INVALID_TAG_COUNT(400, "최대 2개 까지 선택 가능합니다"),
Expand All @@ -32,7 +31,10 @@ public enum ErrorCode {
// report
NOT_EMPTY_REASON(400, "신고사유는 공란일 수 없습니다."),
PROMISE_ALREADY_REPORT(400, "이미 신고된 글입니다."),
NOT_FOUND_REPORT(404, "해당 신고글을 찾을 수 없습니다.");
NOT_FOUND_REPORT(404, "해당 신고글을 찾을 수 없습니다."),

//image
FILE_EXTENSION_INVALID(400, "파일 확장자가 유효하지 않습니다.");

private final int httpStatus;
private final String message;
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/com/wandering/Do/global/s3/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.wandering.Do.global.s3;

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

@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 amazonS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(region)
.build();
}
}
57 changes: 57 additions & 0 deletions src/main/java/com/wandering/Do/global/s3/S3Util.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.wandering.Do.global.s3;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.wandering.Do.global.s3.exception.FileExtensionInvalidException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

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

@Slf4j
@Component
@RequiredArgsConstructor
public class S3Util {
@Value("${cloud.aws.s3.bucket}")
private String bucket;

private final AmazonS3 amazonS3;

public String imageUpload(MultipartFile image) {
try {
List<String> list = List.of("jpg", "jpeg", "png");

String[] splitFile = image.getOriginalFilename().split("\\.");

if (splitFile.length > 2)
throw new FileExtensionInvalidException();

String extension = splitFile[1].toLowerCase();

if (list.stream().noneMatch(it -> it.equals(extension)))
throw new FileExtensionInvalidException();

return upload(image);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private String upload(MultipartFile image) throws IOException {
String profileName = bucket + "/" + UUID.randomUUID() + image.getOriginalFilename();
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(image.getInputStream().available());
amazonS3.putObject(bucket, profileName, image.getInputStream(), metadata);
return amazonS3.getUrl(bucket, profileName).toString();
}

public void deleteImage(String url) {
String key = url.split("com/")[1];
amazonS3.deleteObject(bucket, key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.wandering.Do.global.s3.exception;

import com.wandering.Do.global.exception.CustomException;
import com.wandering.Do.global.exception.ErrorCode;

public class FileExtensionInvalidException extends CustomException {

public FileExtensionInvalidException() {
super(ErrorCode.FILE_EXTENSION_INVALID);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ protected SecurityFilterChain configure(HttpSecurity http) throws Exception {
.requestMatchers(HttpMethod.PATCH, "/home/{pro_id}").authenticated()

.requestMatchers(HttpMethod.GET, "/my").authenticated()
.requestMatchers(HttpMethod.POST, "/my").authenticated()
.requestMatchers(HttpMethod.GET, "/my/reservation").authenticated()
.requestMatchers(HttpMethod.GET, "/my/{pro_id}/info").authenticated()
.requestMatchers(HttpMethod.DELETE, "/my/{pro_id}").authenticated()
Expand Down