s3와 spring를 연결하는 방식을 되게 많이 찾아봤던 것 같다.
이것저것 찾아보면서 버킷을 만들어주고 설정도 해줬다.
설정부분은 생략!
implementation group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.12.172'
package com.hanghae.Today.sHouse.config;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
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.access-key}")
private String accessKey;
@Value("${cloud.aws.credentials.secret-key}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
}
}
@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class PostService {
private final PostRepository postRepository;
private final AmazonS3 amazonS3;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
//게시글 등록
@Transactional
public Post createPost(UserDetailsImpl userDetails, MultipartFileDto requestDto) {
User user = userDetails.getUser();
int size = requestDto.getSize();
String type = requestDto.getType();
String style = requestDto.getStyle();
String area = requestDto.getArea();
MultipartFile imageUrl = requestDto.getImageUrl();
String content = requestDto.getContent();
//s3 관련
String fileName = createFileName(imageUrl.getOriginalFilename());
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(imageUrl.getSize());
objectMetadata.setContentType(imageUrl.getContentType());
System.out.println(bucket);
try(InputStream inputStream = imageUrl.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
} catch(IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "이미지 업로드에 실패했습니다.");
}
String imgUrl = amazonS3.getUrl(bucket, fileName).toString();
PostRequestDto postRequestDto = new PostRequestDto(size, type, style, area, imgUrl, content);
Post post = new Post(user, postRequestDto);
postRepository.save(post);
return post;
}
////////////////////////------------S3관련---------------//////////////////////////////
public void deleteImage(String fileName) {
amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName));
}
private String createFileName(String fileName) {
return UUID.randomUUID().toString().concat(getFileExtension(fileName));
}
private String getFileExtension(String fileName) {
try {
return fileName.substring(fileName.lastIndexOf("."));
} catch (StringIndexOutOfBoundsException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다.");
}
}
}
@RequiredArgsConstructor
@RestController
public class PostController {
private final PostService postService;
//게시글 등록
@PostMapping("/api/post")
public ResponseEntity<Post>createPost(@AuthenticationPrincipal UserDetailsImpl userDetails, MultipartFileDto requestDto){
return new ResponseEntity<>(postService.createPost(userDetails, requestDto), HttpStatus.CREATED);
}
}
그런데 예상치 못한 오류가 발생했다.
곧바로 다른 에러가 발생했다.
logging.level.com.amazonaws.util.EC2MetadataUtils=error
이 값을 넣어주면 된다!그런데 또 에러?????? 지난 주에 사진 업로드 담당하셨던 팀원분 리스펙... 역시 나만빼고 고수야,,
알고보니 이 위에 에러들도 ACL을 비활성화 해놓은 자랑스러운 내 손가락 덕분!!
무튼 이후에 실행해보니 너무 잘된다!
클라이언트에 전송해줘야 되다보니
url 형식으로 바꿔서 내려보냈다!(코드 받았다)
끝!