티스토리 뷰

반응형

 

안녕하십니까

Java Spring boot를 이용한 API 개발 중 AWS S3에 이미지 파일을 관리해야 하는 작업이 있어 진행을 해봤습니다.

 

Java에서 S3나 그 외에 관련된 기능들을 사용하려면 SDK를 Dependency추가해줘야 합니다.

 

Gradle 4.6 이상 

group 'aws.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
  mavenCentral()
}

dependencies {
    implementation 'com.amazonaws:aws-java-sdk-bom:1.11.228'
    implementation 'com.amazonaws:aws-java-sdk-s3'
}

 

Gradle 4.6 미만

group 'aws.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
  mavenCentral()
}

buildscript {
  repositories {
      mavenCentral()
  }
  dependencies {
      classpath "io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE"
  }
}

apply plugin: "io.spring.dependency-management"

dependencyManagement {
  imports {
      mavenBom 'com.amazonaws:aws-java-sdk-bom:1.11.228'
  }
}

dependencies {
  compile 'com.amazonaws:aws-java-sdk-s3'
}

 

저 같은 경우는 IDE에서는 3 버전을, 실 서버에서는 5 버전 대를 사용했기 때문에 dependencies에도 넣어주고 mavenBom도 추가해줬습니다.

 

추가를 완료 하였다면 이제 사용을 하면 되는데, 사용을 하기 전 우리는 서비스 클라이언트를 생성해줘야 합니다.

이 서비스 클라이언트를 만들어 줘야 S3, CloudWatch 등 여러 서비스 들을 이용하실 수 있습니다.

 

Amazon Web Services에 요청하려면 먼저 서비스 클라이언트 객체를 만듭니다. 권장 방법은 서비스 클라이언트 빌더를 사용하는 것입니다.

 

각 AWS 서비스에는 서비스 API의 각 작업에 대한 메서드를 포함하는 서비스 인터페이스가 있습니다.

예를 들어 Amazon DynamoDB의 서비스 인터페이스 이름은 AmazonDynamoDB입니다. 각 서비스 인터페이스마다 서비스 인터페이스의 구현을 생성하는 데 사용할 수 있는 해당하는 클라이언트 빌더가 있습니다. DynamoDB용 클라이언트 빌더 클래스 이름은 AmazonDynamoDBClientBuilder입니다.

 

우리는 S3를 이용할 것이니 서비스 인터페이스 이름은 AmazonS3라는 인터페이스를 사용할 것이며, 클라이언트 빌더 이름은 AmazonS3 ClientBuilder가 될 것입니다.

@Configuration
@EnableWebMvc
public class AWSConfiguration implements WebMvcConfigurer {
	
	@Value("${AWS.ACESSKEY}")
	private String accessKey;
	
	@Value("${AWS.SECRETKEY}")
	private String secretKey;
	
	
	@Bean
	public BasicAWSCredentials AwsCredentials() {
		BasicAWSCredentials AwsCreds = new BasicAWSCredentials(accessKey, secretKey);	
		return AwsCreds;
	}	
	
	@Bean
	public AmazonS3 AwsS3Client() {
		
		AmazonS3 s3Builder = AmazonS3ClientBuilder.standard()
				.withRegion(Regions.AP_NORTHEAST_2)
				.withCredentials(new AWSStaticCredentialsProvider(this.AwsCredentials()))
				.build();	

		return s3Builder;
	}

이제 기능을 구현하면 되는데요. 저는 S3를 이용한 GET, UPLOAD, DELETE를 구현할 것입니다.

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class AwsS3Service {

	@Autowired
	private AmazonS3 s3Client;

	@Value("${AWS.BUCKET}")
	private String bucketName;

	public void uploadObject(MultipartFile multipartFile, String storedFileName) throws IOException {

		SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
		ObjectMetadata omd = new ObjectMetadata();
		omd.setContentType(multipartFile.getContentType());
		omd.setContentLength(multipartFile.getSize());
		omd.setHeader("filename", multipartFile.getOriginalFilename());

		// Copy file to the target location (Replacing existing file with the same name)
		s3Client.putObject(new PutObjectRequest(bucketName + "/" + date.format(new Date()), storedFileName,
				multipartFile.getInputStream(), omd));

	}

	public void deleteObject(String date, String storedFileName) throws AmazonServiceException {

		s3Client.deleteObject(new DeleteObjectRequest(bucketName + "/" + date, storedFileName));

	}

	public Resource getObject(String date, String storedFileName) throws IOException {
		S3Object o = s3Client.getObject(new GetObjectRequest(bucketName + "/" + date, storedFileName));
		S3ObjectInputStream objectInputStream = o.getObjectContent();
		byte[] bytes = IOUtils.toByteArray(objectInputStream);
		
		Resource resource = new ByteArrayResource(bytes);
		return resource;
	}
	
}

위의 코드에서 보면 bucketName + "/" + date가 있는데, 이 부분이 폴더 이름이 될 것입니다.

그리고 getObject 부분은 예제와 좀 다르게 구현을 하였는데, Restful API 방식으로 데이터를 전달하기 위해 org.springframework.core.io.Resource를 활용하였습니다.

 

그리고 그냥 resposne로 보낼 시 File name이 null로 전송되기 때문에 다음과 같이 설정을 해줘야 합니다.

        Resource resource = imageService.loadFileAsResource(date, fileName);

        // Try to determine file's content type
        String contentType = null;
        try {
            contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
        } catch (IOException ex) {
            log.info("Could not determine file type.");
        }

        // Fallback to the default content type if type could not be determined
        if(contentType == null) {
            contentType = "application/octet-stream";
        }

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
                .body(resource);

 

postman으로 테스트 할 시 제대로 파일을 받을 수 있는 것을 확인 하실 수 있습니다.

 

 

출처 및 참고

Java SDK 사용

https://docs.aws.amazon.com/ko_kr/sdk-for-java/v1/developer-guide/setup-project-gradle.html

 

Java S3

https://docs.aws.amazon.com/ko_kr/sdk-for-java/v1/developer-guide/examples-s3-objects.html#upload-object

반응형

'BackEnd > Java' 카테고리의 다른 글

pm2 java  (0) 2019.09.24
Log4j2 날짜별 폴더 생성 & Level별 로그 생성  (2) 2019.09.04
Java send HTTP request  (0) 2019.04.02
Spring boot + Mybatis 연결하기  (0) 2019.03.26
Spring boot Redis 사용하기  (3) 2019.03.12
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함