(error) s3 사진 업로드 하고싶어요😢

전성영·2022년 6월 17일
0

Error

목록 보기
11/16

s3와 spring를 연결하는 방식을 되게 많이 찾아봤던 것 같다.
이것저것 찾아보면서 버킷을 만들어주고 설정도 해줬다.
설정부분은 생략!

build.gradle

	implementation group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.12.172'

S3Config.java

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

postService.java


@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 + ") 입니다.");
        }
    }
}

PostController.java

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

그런데 예상치 못한 오류가 발생했다.

  • 1. Failed to connect to service endpoint

    찾아보니 EC2 인스턴스가 아닌 다른곳에서 해당 애플리케이션을 실행할 때는 환경변수 "AWS_EC2_METADATA_DISABLED" 값을 true로 해주면 된다고 한다.

곧바로 다른 에러가 발생했다.

  • 2. EC2 Instance Metadata Service is disabled

    EC2 인스턴스 메타데이터 조회 API 호출로직이 실행되지 않았다는 뜻이지만 에러가 아니라고 한다.
    그래도 지우는 방법은 application.properties에 logging.level.com.amazonaws.util.EC2MetadataUtils=error 이 값을 넣어주면 된다!

그런데 또 에러?????? 지난 주에 사진 업로드 담당하셨던 팀원분 리스펙... 역시 나만빼고 고수야,,

  • 3. File upload failed : AccessControlListNotSupported: The bucket does not allow ACLs

알고보니 이 위에 에러들도 ACL을 비활성화 해놓은 자랑스러운 내 손가락 덕분!!
무튼 이후에 실행해보니 너무 잘된다!
클라이언트에 전송해줘야 되다보니
url 형식으로 바꿔서 내려보냈다!(코드 받았다)

끝!

profile
Slow and Steady

0개의 댓글