- S3 : (Simple Storage Service) 아마존에서 제공하는 인터넷용 스토리지 서비스.
웹 등에서 사용되는 사진, 텍스트 등 여러 데이터를 손쉽게 저장 및 관리할 수 있다.- IAM: (Identity and Access Management) AWS 리소스들에 대한 접근을 제어할 수 있는 서비스.
권한을 부여 혹은 제한하여 리소스 보관의 안정성을 높인다.
아래 설정들을 해준다
드디어 버킷이 생성됨
생성된 버킷에 사진을 업로드 해본다
올린 파일 확인해보기
거부당함..
위 두가지 편집하기!!
다시 클릭해보면 이제 제대로 사진이 나온다!
사용자가 생성되었다.
엑세스 키를 만들자
드디어 엑세스키와 비밀 엑세스 키를 획득했다..😓 근데 안됨...?
ACL 활성화로 변경! 하니 되었다.
사진이 잘 올라갔다.
올린 파일이 화면에 뙇! 나타났다.
구글링을 해보니 코드는 정형화되어 있는 것 같다.
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 S3Config {
@Value("${cloud.aws.credentials.accessKey}") // 엑세스키 application/properties에
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}") // 비밀 엑세스키 application/properties에
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public AmazonS3 amazonS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(region)
.build();
}
}
@Service
@RequiredArgsConstructor
public class AwsS3Service {
@Value("${cloud.aws.s3.bucket}")
private String bucket;
private final AmazonS3 amazonS3;
public List<String> uploadFile(List<MultipartFile> multipartFile) {
List<String> fileNameList = new ArrayList<>();
multipartFile.forEach(file -> {
String fileName = createFileName(file.getOriginalFilename());
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.getSize());
objectMetadata.setContentType(file.getContentType());
try(InputStream inputStream = file.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
} catch(IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "이미지 업로드에 실패했습니다.");
}
fileNameList.add(fileName);
});
return fileNameList;
}
📍@RequestPart는 multipart/form-data에 특화된 어노테이션이다.
@PostMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public String createPost( @ModelAttribute PostRequestDto requestDto, @RequestPart(value = "multipartFileList", required = false) List<MultipartFile> multipartFileList, @AuthenticationPrincipal UserDetailsImpl userDetails, RedirectAttributes redirectAttributes) {