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

Fix merge conflicts

parent 9c59e294
No related branches found
No related tags found
1 merge request!2s3 func merge
......@@ -4,6 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
/application-aws.properites
**/*.properties
......
......@@ -36,12 +36,11 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl: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') {
......
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