- 1. build.gradle¿¡ ÀÇÁ¸¼º Ãß°¡Çϱâ
- 2. application.yml¿¡ ¹öŶ ¹× ÀÚ°Ý Á¤º¸ ÀÔ·ÂÇϱâ
- 3. Amazon °èÁ¤°ú ¿¬°áÇϱâ
- 4. S3 ¹öŶ¿¡ ÀÖ´Â ÆÄÀÏ ´Ù¿î·ÎµåÇϱâ
1. build.gradle¿¡ ÀÇÁ¸¼º Ãß°¡Çϱâ
Spring°ú AWS¸¦ ¿¬µ¿½ÃÅ°±â À§ÇØ spring-cloud-starter-awsÀ» »ç¿ëÇÑ´Ù.
dependencies {
// aws s3
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.2.6.RELEASE'
}
2. application.yml¿¡ ¹öŶ ¹× ÀÚ°Ý Á¤º¸ ÀÔ·ÂÇϱâ
cloud:
aws:
credentials:
instance-profile: false
access-key: {IAM MY_ACCESS_KEY ÀÔ·Â}
secret-key: {IAM MY_SECERT_KEY ÀÔ·Â}
region:
static: ap-northeast-2
stack:
auto: false
logging:
level:
com:
amazonaws:
util:
EC2MetadataUtils: error
aws:
s3:
bucket: {¹öŶ À̸§}
¾Æ·¡ÀÇ ¿¡·¯°¡ ¹ß»ýÇϸé cloud.aws.stack.auto=false¸¦ ³Ö¾îÁÖ¸é µÈ´Ù.
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.aws.core.env.ResourceIdResolver.BEAN_NAME': Invocation of in
...
3. Amazon °èÁ¤°ú ¿¬°áÇϱâ
Amazon IAM°èÁ¤°ú ¿¬°áÇϱâ À§ÇÑ ConfigŬ·¡½º¸¦ »ý¼ºÇÑ´Ù. (Âü°í)
.withRegion() Áö¿ª ¼³Á¤À» Çʼö·Î ÇÏ°í AWSCredentialsProvider ÀÎÅÍÆäÀ̽º¸¦ ÀÔ·ÂÀ¸·Î »ç¿ëÇϴ Ŭ¶óÀ̾ðÆ® ºô´õ¿¡ ÀÚ°Ý Áõ¸í °ø±ÞÀÚ³ª °ø±ÞÀÚ Ã¼ÀÎÀÇ ÀνºÅϽº(accessKey, secretKey)¸¦ Á¦°øÇÑ´Ù.
@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
@Primary
public BasicAWSCredentials awsCredentialsProvider(){
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKey, secretKey);
return basicAWSCredentials;
}
@Bean
public AmazonS3 amazonS3() {
AmazonS3 s3Builder = AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentialsProvider()))
.build();
return s3Builder;
}
}
4. S3 ¹öŶ¿¡ ÀÖ´Â ÆÄÀÏ ´Ù¿î·ÎµåÇϱâ
ÀÌÁ¦ ´Ù¿î·Îµå¸¦ Çϱâ À§ÇØ @Service Ŭ·¡½º¸¦ »ý¼ºÇÑ´Ù. (Âü°í)
1. AmazonS3 Ŭ¶óÀ̾ðÆ®ÀÇ getObject ¸Þ¼µå¸¦ »ç¿ëÇÏ¿© ´Ù¿î·ÎµåÇÒ ¹öŶ ¹× °´Ã¼ÀÇ À̸§(bucket, storedFileName)À» Àü´ÞÇÏ°í ¸ÅĪÀÌ µÇ¸é S3Object¸¦ ¹ÝȯÇÑ´Ù.
S3Object o = amazonS3.getObject(new GetObjectRequest(bucket, storedFileName));
2. ±×¸®°í S3ObjectÀÇ getObjectContent()¸¦ È£ÃâÇÏ¿© °´Ã¼ÀÇ ³»¿ëÀ» S3ObjectInputStream ÇüÅ·Π°¡Á®¿À°í IOUtilsÀÇ toByteArray() ¸Þ¼Òµå¿¡ ÀÇÇØ ÆÄÀÏÀ» ¸¸µé°í ³»¿ëÀ» ¾²´Â °úÁ¤À» °ÅÄ£´Ù.
* S3ObjectInputStreamÀº Java·Î µ¿ÀÛÇÏ´ÂInputStream°´Ã¼ÀÌ´Ù.
* toByteArray()¾È¿¡¼ ByteArrayOutputStream outputÀ» ÅëÇØ write¸¦ ÇÏ°í °á°ú¹°À» byteArray·Î ¸®ÅÏÇÑ´Ù.
S3ObjectInputStream objectInputStream = o.getObjectContent();
byte[] bytes = IOUtils.toByteArray(objectInputStream);
3. Àü¼ÛÇÏ´Â ÆÄÀÏÀÇ Á¾·ù¿¡ µû¶ó Content-TypeÀ» ÁöÁ¤ÇØÁØ´Ù. À̹ÌÁö´Â "image/jpeg" °°Àº Çü½ÄÀ¸·Î,
±âŸ ÆÄÀÏÀº "application/octet-stream"¸¦ ³Ö¾îÁØ´Ù. ³ª´Â CSVÆÄÀÏÀ» ¹ÞÀ» °ÍÀ̹ǷΠoctet-streamÀ¸·Î ÀÔ·ÂÇß´Ù.
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentDispositionFormData("attachment", fileName);
@Service
@RequiredArgsConstructor
public class DownloadS3 {
private final AmazonS3 amazonS3;
@Value("${aws.s3.bucket}")
private String bucket;
public ResponseEntity<byte[]> getObject(String storedFileName) throws IOException{
S3Object o = amazonS3.getObject(new GetObjectRequest(bucket, storedFileName));
S3ObjectInputStream objectInputStream = o.getObjectContent();
byte[] bytes = IOUtils.toByteArray(objectInputStream);
String fileName = URLEncoder.encode(storedFileName, "UTF-8").replaceAll("\\+", "%20");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentLength(bytes.length);
httpHeaders.setContentDispositionFormData("attachment", fileName);
return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
}
}
ÄÁÆ®·Ñ·¯¿¡ ÇØ´ç ¼ºñ½º ·ÎÁ÷°ú °æ·Î¸¦ ¸ÅÇνÃÄÑÁØ´Ù. ¸¸¾à S3 ¹öŶ¾È¿¡ ÆÄÀÏÀÌ ¾ø°Å³ª ÆÄÀϸíÀÌ ÀÏÄ¡ÇÏÁö ¾Ê´Â´Ù¸é ´Ù¿îÀÌ µÇÁö ¾Ê°í NullException¿¡·¯°¡ ¹ß»ýÇÒ °ÍÀÌ´Ù.
@Controller
@RequiredArgsConstructor
public class S3Controller {
private final DownloadS3 downloadS3;
@GetMapping("/csv_download")
public ResponseEntity<byte[]> download() throws IOException {
return downloadS3.getObject("20210520.csv");
}
}
´Ù¿î·Îµå ¼º°ø!