Skip to content
Snippets Groups Projects
Commit fb96f2c3 authored by donghyun's avatar donghyun
Browse files

Merge branch 'anak' into 'master'

s3 func merge

See merge request !2
parents 9c59e294 b4589469
No related branches found
No related tags found
1 merge request!2s3 func merge
...@@ -4,6 +4,7 @@ build/ ...@@ -4,6 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar !gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/ !**/src/main/**/build/
!**/src/test/**/build/ !**/src/test/**/build/
/application-aws.properites
**/*.properties **/*.properties
......
...@@ -36,12 +36,11 @@ dependencies { ...@@ -36,12 +36,11 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
// AWS S3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
} }
tasks.named('test') { tasks.named('test') {
......
package umc.spring.file.config;
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 AwsConfig {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public AmazonS3 amazonS3() {
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
\ No newline at end of file
package umc.spring.file.controller;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import umc.spring.file.service.AmazonS3Service;
import umc.spring.file.service.S3Service;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/file")
public class FileController {
private final AmazonS3Service amazon3SService;
@PostMapping("/uploads")
public ResponseEntity<Object> uploadFiles(
@RequestParam(value = "uploadFilePath") String uploadFilePath,
@RequestPart(value = "files") List<MultipartFile> multipartFiles) {
return ResponseEntity
.status(HttpStatus.OK)
.body(amazon3SService.uploadFiles(uploadFilePath, multipartFiles));
}
@DeleteMapping("/delete")
public ResponseEntity<Object> deleteFile(
@RequestParam(value = "uploadFilePath") String uploadFilePath,
@RequestParam(value = "uuidFileName") String uuidFileName) {
return ResponseEntity
.status(HttpStatus.OK)
.body(amazon3SService.deleteFile(uploadFilePath, uuidFileName));
}
@GetMapping("/get")
public void getFile(HttpServletResponse response,
@RequestParam String uploadFilePath,
@RequestParam String uuidFileName) {
try {
InputStream inputStream = amazon3SService.getFile(uploadFilePath, uuidFileName);
if (inputStream != null) {
byte[] buffer = new byte[4048];
int bytesRead;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
try (OutputStream outStream = response.getOutputStream()) {
while ((bytesRead = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
}
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
package umc.spring.file.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@Builder
public class S3FileDto {
private String originalFileName;
private String uploadFileName;
private String uploadFilePath;
private String uploadFileUrl;
}
\ No newline at end of file
package umc.spring.file.service;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import umc.spring.file.domain.S3FileDto;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@RequiredArgsConstructor
@Service
public class AmazonS3Service {
@Value("${cloud.aws.s3.bucket}")
private String bucketName;
private final AmazonS3 amazonS3;
/**
* S3로 파일 업로드
*/
public List<S3FileDto> uploadFiles(String uploadFilePath, List<MultipartFile> multipartFiles) {
List<S3FileDto> s3files = new ArrayList<>();
// String uploadFilePath = fileType + "/" + getFolderName();
for (MultipartFile multipartFile : multipartFiles) {
String originalFileName = multipartFile.getOriginalFilename();
String uploadFileName = getUuidFileName(originalFileName);
String uploadFileUrl = "";
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(multipartFile.getSize());
objectMetadata.setContentType(multipartFile.getContentType());
try (InputStream inputStream = multipartFile.getInputStream()) {
String keyName = uploadFilePath + "/" + uploadFileName; // ex) 구분/파일.확장자
// S3에 폴더 및 파일 업로드
// 외부에 공개하는 파일인 경우 Public Read 권한을 추가, ACL 확인
amazonS3.putObject(
new PutObjectRequest(bucketName, keyName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
// S3에 업로드한 폴더 및 파일 URL
uploadFileUrl = amazonS3.getUrl(bucketName, keyName).toString();
} catch (IOException e) {
e.printStackTrace();
log.error("Filed upload failed", e);
}
s3files.add(
S3FileDto.builder()
.originalFileName(originalFileName)
.uploadFileName(uploadFileName)
.uploadFilePath(uploadFilePath)
.uploadFileUrl(uploadFileUrl)
.build());
}
return s3files;
}
/**
* S3에 업로드된 파일 삭제
*/
public String deleteFile(String uploadFilePath, String uuidFileName) {
String result = "success";
try {
String keyName = uploadFilePath + "/" + uuidFileName; // ex) 구분/파일.확장자
boolean isObjectExist = amazonS3.doesObjectExist(bucketName, keyName);
if (isObjectExist) {
amazonS3.deleteObject(bucketName, keyName);
} else {
result = "file not found";
}
} catch (Exception e) {
log.debug("Delete File failed", e);
}
return result;
}
/**
* S3에서 파일 읽어오기
*/
public InputStream getFile(String uploadFilePath, String uuidFileName) {
String keyName = uploadFilePath + "/" + uuidFileName; // ex) 구분/파일.확장자
boolean isObjectExist = amazonS3.doesObjectExist(bucketName, keyName);
if (isObjectExist) {
S3Object s3object = amazonS3.getObject(bucketName, keyName);
return s3object.getObjectContent();
} else {
log.error("File not found");
return null;
}
}
/**
* UUID 파일명 반환
*/
public String getUuidFileName(String fileName) {
String ext = fileName.substring(fileName.indexOf(".") + 1);
return UUID.randomUUID().toString() + "." + ext;
}
/**
* 년/월/일 폴더명 반환
*/
private String getFolderName() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date date = new Date();
String str = sdf.format(date);
return str.replace("-", "/");
}
}
\ No newline at end of file
package umc.spring.file.service;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Date;
/* S3Service.java */
@Slf4j
@RequiredArgsConstructor
@Service
public class S3Service {
@Value("${cloud.aws.s3.bucket}")
private String bucket;
private final AmazonS3 amazonS3;
/* 1. 파일 업로드 */
public String upload(MultipartFile multipartFile, String s3FileName) throws IOException {
// 메타데이터 생성
ObjectMetadata objMeta = new ObjectMetadata();
objMeta.setContentLength(multipartFile.getInputStream().available());
// putObject(버킷명, 파일명, 파일데이터, 메타데이터)로 S3에 객체 등록
amazonS3.putObject(new PutObjectRequest(bucket, s3FileName, multipartFile.getInputStream(), objMeta)
.withCannedAcl(CannedAccessControlList.PublicRead));
// 등록된 객체의 url 반환 (decoder: url 안의 한글 or 특수문자 깨짐 방지)
return URLDecoder.decode(amazonS3.getUrl(bucket, s3FileName).toString(), "utf-8");
}
/* 2. 파일 삭제 */
public void delete (String keyName) {
try {
// deleteObject(버킷명, 키값)으로 객체 삭제
amazonS3.deleteObject(bucket, keyName);
} catch (AmazonServiceException e) {
log.error(e.toString());
}
}
/* 3. 파일의 presigned URL 반환 */
public String getPresignedURL (String keyName) {
String preSignedURL = "";
// presigned URL이 유효하게 동작할 만료기한 설정 (2분)
Date expiration = new Date();
Long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 2;
expiration.setTime(expTimeMillis);
try {
// presigned URL 발급
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucket, keyName)
.withMethod(HttpMethod.GET)
.withExpiration(expiration);
URL url = amazonS3.generatePresignedUrl(generatePresignedUrlRequest);
preSignedURL = url.toString();
} catch (Exception e) {
log.error(e.toString());
}
return preSignedURL;
}
}
\ No newline at end of file
cloud.aws.s3.bucket=anak-s3
cloud.aws.stack.auto=false
cloud.aws.region.static=ap-northeast-2
cloud.aws.credentials.accessKey=AKIAUK4OA4SHAQ4Y76RL
cloud.aws.credentials.secretKey=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
\ No newline at end of file
#spring.config.activate.on-profile=aws
spring.profiles.active=aws
# mySql
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1234
spring.jpa.properties.hibernate.jdbc.batch_size=100
# jpa
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.open-in-view=false
# MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB
jwt.secret=secret
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment