SPRING
2022.05.02 / 16:11

[Spring/ AWS] Spring Boot S3¸¦ ÀÌ¿ëÇÏ¿© File ´Ù¿î·ÎµåÇϱâ

ÄÚÄÚ·Î
Ãßõ ¼ö 137

[Spring/ AWS] Spring Boot S3¸¦ ÀÌ¿ëÇÏ¿© File ´Ù¿î·ÎµåÇϱâ

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");
    }
}

 

´Ù¿î·Îµå ¼º°ø!