JisooPyo / KP3C-backoffice-project

스레드와 트위터를 참고하여 SNS 사이트를 만들어보고 백오피스까지 구현해보는 프로젝트
1 stars 2 forks source link

[Feature] 게시물 멀티미디어 기능 구현 / 다중파일 업로드 + 이미지 AWS S3에 저장, 게시글 작성 및 조회 프론트와 연결 #55

Closed hyewon218 closed 1 year ago

hyewon218 commented 1 year ago

관련 Issue #6

변경 사항

김태선 튜터님 강의를 듣고 View를 반환하기 위한 클래스는 PostViewController PostViewService 이렇게 따로 추가하였습니다.

AWS S3 사용을 위해 application/properties 작성하기

(천만원 과금을 당할 수 있다고 합니다….😱)

cloud.aws.credentials.accessKey= cloud.aws.credentials.secretKey= cloud.aws.s3.bucket= cloud.aws.region.static=ap-northeast-2 cloud.aws.stack.auto-=false

AwsS3Config

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 AwsS3Config {
    @Value("${cloud.aws.credentials.accessKey}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secretKey}")
    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();
    }

}

버킷 생성 후, 접근을 위한 IAM 계정을 생성했다면 access key, secret access key 등이 제공되었을 텐데, 그 정보를 받아오는 파일입니다. application/properties 파일에 작성한 값들을 읽어와서 AmazonS3Client 객체를 만들어 Bean으로 주입해주는 것입니다.

AwsS3Service

@Service
@RequiredArgsConstructor
public class AwsS3Service {

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    private final AmazonS3 amazonS3;

    public List<String> uploadImage(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;
    }
    private String createFileName(String fileName) {
        return UUID.randomUUID().toString().concat(getFileExtension(fileName));
    }

uploadImage 들고온 파일들을 forEach문을 사용해 돌면서 파일 정보를 읽어오고 AmazonS3 라이브러리를 활용해 putObject를 통해서 업로드 해주었습니다. 업로드 할 때 한글명을 가진 파일의 경우 인식을 제대로 못해 외계어로 올라가는 경우가 많았는데, 이 때문에 파일이름을 랜덤으로 생성해주는 createFileName 메서드를 따로 만들어 해당 이름으로 업로드 되도록 하였습니다.

PostViewController

@RequestPart는 multipart/form-data에 특화된 어노테이션 어노테이션도 많아서 많이 헷갈렸습니다..MultipartFile 받아올 때는 @RequestPart 어노테이션 사용하기!

    @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) {

post-view.html

 <img th:each="imageUrl : ${post.imageUrlList}" th:src="|https://kp3c-aws-config-storage.s3.ap-northeast-2.amazonaws.com/${imageUrl.getImgUrl()}|" width="300" height="300"/>

버킷 url 파일 이름 앞까지 그대로 박아놨는데...

<img src="https://{bucket-name}.s3.{region-name}.amazonaws.com/{파일명}"> 

이렇게 어떻게 수정해야할지..고민해보겠습니다


실행해보기

http://localhost:8080/kp3c-view/post E5AC6575-1E7D-49B8-A0B1-B69F21F246DA 이미지 선택+글 작성하고 게시 버튼 누르면 생성된 게시글 조회 화면으로 이동! -> 선택한 이미지들이 잘 조회됩니다! 수정, 삭제는 시간이 부족하여...


http://localhost:8080/kp3c-view/post/16

B45A3345-BFB2-4A4E-BB32-D6E79AADB861

AWS S3에 파일 올라간 것 확인

51AEA334-1DA4-4149-A377-00E0642F45FC s3에 잘 올라갔습니다.

DB 저장 확인

post_image 테이블 BF1185C1-0D82-4B7D-8BD0-403326B2E3F2_4_5005_c posts 테이블 79C2E2F4-16F6-4075-86FA-540AB5387CFF_4_5005_c DB에도 저장이 잘 되었습니다.

Todo List

aws s3를 사용하기 위해서는 버킷생성+IAM 계정생성을 해야햐는데 저는 이 부분에서 너무 애를 먹었습니다... 남은 시간동안 예외처리 꼼꼼하게 하도록 하겠습니다!

Check List

- [x] 포스트맨으로 체크해 보았나요?
JisooPyo commented 1 year ago

와!!! 머시따!!!! aws!!!!