본문 바로가기

Back/AWS_Back

[AWS][S3]Presinged Image upload + img 태그 src 설정

개요.

aws에 이미지를 올리고 해당 이미지를 호스팅 하는것까지 진행

aws s3에 이미지를 올리려면 일반적인 예제들로는 AWS 키가 필요하다. 키는 서버에서 관리되며 클라이언트로 전달되면 안되므로 일반적으로 다음과 같은 구조를 띈다.

위와 같이 되면 이미지의 크기가 작고 수가 적으면 괜찮지만, 크고 많아지면 문제가 발생할 여지가 높다. 

이를 위해 S3에서는 미리 파일을 받을 자리를 마련하고 POST 메소드를 이용하여 파일을 전달받아 넣을 수 있도록 Presined_url, Presined_post를 제공하고 있다. 

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_post

 

S3 — Boto3 Docs 1.18.61 documentation

A dictionary with two elements: url and fields. Url is the url to post to. Fields is a dictionary filled with the form fields and respective values to use when submitting the post. For example: {'url': 'https://mybucket.s3.amazonaws.com 'fields': {'acl': '

boto3.amazonaws.com

이번 게시글에선 파이썬 백엔드를 기준으로 한다.

 

준비물 

- 이미지 업로드를 위한 AWS 계정, S3 버켓

 

 


1.URL 발급

def create_presigned_post(bucket_name, object_name,expiration=3600):
   

    # Generate a presigned S3 POST URL
    s3_client = boto3.client('s3',
    aws_access_key_id=AWS_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SECRET_ACCESS_KEY
    )
    try:
        response = s3_client.generate_presigned_post(bucket_name,
                                                     object_name,
                                                     Fields={'ACL': 'public-read',
                                                     'Content-Type':'image/jpeg'},
                                                     Conditions=[{'ACL': 'public-read'},{'Content-Type':'image/jpeg'}],
                                                     ExpiresIn=expiration)
    except ClientError as e:
        print(e)
        return None

    # The response contains the presigned URL and required fields
    return response

boto3.client에서 해당 기능을 호출 할 수 있다. 버켓이름과 파일이름을 정해서 넣을 수 있다. 

중요한 점은 Fileds 와 Conditions이다. 두개는 옵션을 넣어 주는데, 두가지 동시에 넣어주어야 에러가 발생하지 않는다.

Fileds는 dictionary, Conditions 는 List 형태를 가지며, 잘모르겠다면 위의 예시를 보자.

ACL : public-read는 모든사람의 읽기 권한을 허용해준다.

이부분을 읽기로 바꿔줘야 외부에서 읽을 수 있다.

Contents-Types : image/jpeg는 해당 파일의 메타데이터를 설정해 준다. 

메타데이터의 종류에 따라 이 파일이 이미지로 호스팅 되는지 아니면 그냥 파일로 호스팅 되는지 바뀌는 듯 하다.

객체 URL을 통해 해당 파일에 접근 할 수 있는데, 이미지는 열려서 브라우저에 띄워져야 한다.

만약 다운로드 된다면 이부분을 수정해 주면 된다. 

 

2. 1번의 함수를 호출하면 URL과 해당 URL 의 정보를 담은 fileds가 리턴된다.

클라이언트로 해당 내용을 보내 form data로 전송하면 된다.

s3_submit(URI, fields, files) {

                var data = new FormData();
                

                Object.keys(fields).forEach(key => {
                    data.append(key, fields[key]);
                });
                data.append("file", files)
                
                console.log(data);
                
                axios.post(URI,
                        data, {
                            headers: {
                                'Content-Type': 'multipart/form-data'
                            }
                        }
                    )
                    .then(function (response) {
                        console.log(response);
                    })
                    .catch(function (error) {
                        console.log(error);
                    });
            },
},

위 코드는 vue.js 에서 axios를 이용하여 전송하는 예시이다.

결과로 URL에 fields 를 그대로 폼데이터로 넣고 파일을 추가하여 전송 하였다.

 

3.img 태그의 src로 해다 파일의 객체 URL을 넣으면 화면에 이미지가 뜬다.

s3에 올라간 파일 상단부분에서 찾을 수 있으며 다음과 같은 구조를 갖는다,

https://{버켓이름}.s3.{리전이름}.amazonaws.com/{파일이름}