-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
223 additions
and
15 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 111 additions & 1 deletion
112
seventhSeminar/src/main/java/sopt/org/fourthSeminar/aws/S3Service.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,112 @@ | ||
package sopt.org.fourthSeminar.aws;public class S3Service { | ||
package sopt.org.fourthSeminar.aws; | ||
|
||
|
||
import com.amazonaws.auth.AWSStaticCredentialsProvider; | ||
import com.amazonaws.auth.BasicAWSCredentials; | ||
import com.amazonaws.services.s3.AmazonS3; | ||
import com.amazonaws.services.s3.AmazonS3Client; | ||
import com.amazonaws.services.s3.AmazonS3ClientBuilder; | ||
import com.amazonaws.services.s3.model.CannedAccessControlList; | ||
import com.amazonaws.services.s3.model.ObjectMetadata; | ||
import com.amazonaws.services.s3.model.PutObjectRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.multipart.MultipartFile; | ||
import sopt.org.fourthSeminar.controller.exception.Error; | ||
import sopt.org.fourthSeminar.controller.exception.model.BadRequestException; | ||
import sopt.org.fourthSeminar.controller.exception.model.NotFoundException; | ||
import javax.annotation.PostConstruct; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class S3Service { | ||
private final AmazonS3 amazonS3; | ||
|
||
@Value("${cloud.aws.credentials.accessKey}") | ||
private String accessKey; | ||
|
||
@Value("${cloud.aws.credentials.secretKey}") | ||
private String secretKey; | ||
|
||
@Value("${cloud.aws.s3.bucket}") | ||
private String bucket; | ||
|
||
@Value("${cloud.aws.region.static}") | ||
private String region; | ||
|
||
@PostConstruct | ||
public AmazonS3Client amazonS3Client() { | ||
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); | ||
return (AmazonS3Client) AmazonS3ClientBuilder.standard() | ||
.withRegion(region) | ||
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) | ||
.build(); | ||
} | ||
|
||
public String uploadImage(MultipartFile multipartFile, String folder) { | ||
String fileName = createFileName(multipartFile.getOriginalFilename()); | ||
ObjectMetadata objectMetadata = new ObjectMetadata(); | ||
objectMetadata.setContentLength(multipartFile.getSize()); | ||
objectMetadata.setContentType(multipartFile.getContentType()); | ||
|
||
try(InputStream inputStream = multipartFile.getInputStream()) { | ||
amazonS3.putObject(new PutObjectRequest(bucket+"/"+ folder + "/image", fileName, inputStream, objectMetadata) | ||
.withCannedAcl(CannedAccessControlList.PublicRead)); | ||
return amazonS3.getUrl(bucket+"/"+ folder + "/image", fileName).toString(); | ||
} catch(IOException e) { | ||
throw new NotFoundException(Error.NOT_FOUND_SAVE_IMAGE_EXCEPTION, Error.NOT_FOUND_SAVE_IMAGE_EXCEPTION.getMessage()); | ||
} | ||
} | ||
|
||
public List<String> uploadImages(List<MultipartFile> multipartFileList, String folder) { | ||
List<String> uploadImageUrls = new ArrayList<>(); | ||
String fileName; | ||
ObjectMetadata objectMetadata; | ||
for (MultipartFile multipartFile : multipartFileList) { | ||
fileName = createFileName(multipartFile.getOriginalFilename()); | ||
objectMetadata = new ObjectMetadata(); | ||
objectMetadata.setContentLength(multipartFile.getSize()); | ||
objectMetadata.setContentType(multipartFile.getContentType()); | ||
|
||
try(InputStream inputStream = multipartFile.getInputStream()) { | ||
amazonS3.putObject(new PutObjectRequest(bucket+"/"+ folder + "/image", fileName, inputStream, objectMetadata) | ||
.withCannedAcl(CannedAccessControlList.PublicRead)); | ||
uploadImageUrls.add(amazonS3.getUrl(bucket+"/"+ folder + "/image", fileName).toString()); | ||
} catch(IOException e) { | ||
throw new NotFoundException(Error.NOT_FOUND_SAVE_IMAGE_EXCEPTION, Error.NOT_FOUND_SAVE_IMAGE_EXCEPTION.getMessage()); | ||
} | ||
} | ||
|
||
return uploadImageUrls; | ||
} | ||
|
||
// 파일명 (중복 방지) | ||
private String createFileName(String fileName) { | ||
return UUID.randomUUID().toString().concat(getFileExtension(fileName)); | ||
} | ||
|
||
// 파일 유효성 검사 | ||
private String getFileExtension(String fileName) { | ||
if (fileName.length() == 0) { | ||
throw new NotFoundException(Error.NOT_FOUND_IMAGE_EXCEPTION, Error.NOT_FOUND_IMAGE_EXCEPTION.getMessage()); | ||
} | ||
ArrayList<String> fileValidate = new ArrayList<>(); | ||
fileValidate.add(".jpg"); | ||
fileValidate.add(".jpeg"); | ||
fileValidate.add(".png"); | ||
fileValidate.add(".JPG"); | ||
fileValidate.add(".JPEG"); | ||
fileValidate.add(".PNG"); | ||
String idxFileName = fileName.substring(fileName.lastIndexOf(".")); | ||
if (!fileValidate.contains(idxFileName)) { | ||
throw new BadRequestException(Error.INVALID_MULTIPART_EXTENSION_EXCEPTION, Error.INVALID_MULTIPART_EXTENSION_EXCEPTION.getMessage()); | ||
} | ||
return fileName.substring(fileName.lastIndexOf(".")); | ||
} | ||
} |
23 changes: 22 additions & 1 deletion
23
seventhSeminar/src/main/java/sopt/org/fourthSeminar/config/swagger/SwaggerConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,23 @@ | ||
package sopt.org.fourthSeminar.config.swagger;public class SwaggerConfig { | ||
package sopt.org.fourthSeminar.config.swagger; | ||
|
||
import io.swagger.v3.oas.models.Components; | ||
import io.swagger.v3.oas.models.OpenAPI; | ||
import io.swagger.v3.oas.models.info.Info; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class SwaggerConfig { | ||
|
||
@Bean | ||
public OpenAPI openAPI() { | ||
Info info = new Info() | ||
.title("SOPT32nd Seminar project") | ||
.description("SOPT32nd Seminar project API Document") | ||
.version("1.0.0"); | ||
|
||
return new OpenAPI() | ||
.components(new Components()) | ||
.info(info); | ||
} | ||
} |
27 changes: 26 additions & 1 deletion
27
...src/main/java/sopt/org/fourthSeminar/controller/dto/request/BoardImageListRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,27 @@ | ||
package sopt.org.fourthSeminar.controller.dto.request;public class BoardImageListDto { | ||
package sopt.org.fourthSeminar.controller.dto.request; | ||
|
||
import lombok.*; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import javax.validation.constraints.NotBlank; | ||
import javax.validation.constraints.NotNull; | ||
import java.util.List; | ||
|
||
@Getter | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class BoardImageListRequestDto { | ||
private List<MultipartFile> boardImages; | ||
|
||
@NotBlank | ||
private String title; | ||
|
||
@NotBlank | ||
private String content; | ||
|
||
@NotNull | ||
private Boolean isPublic; | ||
|
||
public void setBoardImages(List<MultipartFile> boardImages) { | ||
this.boardImages = boardImages; | ||
} | ||
} |
10 changes: 9 additions & 1 deletion
10
.../src/main/java/sopt/org/fourthSeminar/controller/exception/model/BadRequestException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
package sopt.org.fourthSeminar.controller.exception.model;public class BacRequestException { | ||
package sopt.org.fourthSeminar.controller.exception.model; | ||
|
||
import sopt.org.fourthSeminar.controller.exception.Error; | ||
|
||
public class BadRequestException extends SoptException{ | ||
|
||
public BadRequestException(Error error, String message) { | ||
super(error, message); | ||
} | ||
} |
34 changes: 33 additions & 1 deletion
34
seventhSeminar/src/main/java/sopt/org/fourthSeminar/domain/Image.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,34 @@ | ||
package sopt.org.fourthSeminar.domain;public class Image { | ||
package sopt.org.fourthSeminar.domain; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import sopt.org.fourthSeminar.AuditingTimeEntity; | ||
|
||
import javax.persistence.*; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Image extends AuditingTimeEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "board_id", nullable = false, foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT)) | ||
private Board board; | ||
|
||
@Column(nullable = false) | ||
private String imageUrl; | ||
|
||
private Image(Board board, String imageUrl) { | ||
this.board = board; | ||
this.imageUrl = imageUrl; | ||
} | ||
|
||
public static Image newInstance(Board board, String imageUrl) { | ||
return new Image(board, imageUrl); | ||
} | ||
} |
10 changes: 9 additions & 1 deletion
10
seventhSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/ImageRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
package sopt.org.fourthSeminar.infrastructure;public class ImageRepository { | ||
package sopt.org.fourthSeminar.infrastructure; | ||
|
||
|
||
import org.springframework.data.repository.Repository; | ||
import sopt.org.fourthSeminar.domain.Image; | ||
|
||
public interface ImageRepository extends Repository<Image, Long> { | ||
// CREATE | ||
void save(Image image); | ||
} |