Serverless 구성에서 이미지 업로드는 어떻게 해야 합니까?

TL;DR



서명 된 URL을 발행하고 URL을 사용하여 프론트에서 S3에 직접 업로드하는 것이 좋습니다.

흐름
1. 인증된 사용자에게 서명된 URL 발급
2. 서명된 URL을 사용하여 S3에 업로드

개요도


출처

서명된 URL 발급
import boto3
from botocore.config import Config

# 署名付き URL を発行
def get_signature_url(bucket, key, image_size):
    s3_cli = boto3.client('s3', config=Config(signature_version='s3v4'), region_name='ap-northeast-1')
    return s3_cli.generate_presigned_url(
        ClientMethod='put_object',
        Params={'Bucket': bucket, 'Key': key, 'ContentLength': image_size},
        ExpiresIn=300,
        HttpMethod='PUT'
    )

# パラメータ設定
bucket = 'piyopiyo-bucket'    # 任意の S3バケット名
key = 'path/to/hoge.png'      # 任意の S3オブジェクトキー名
image_size = 1000             # 対象ファイルのサイズ

# 実行
signature_url = get_signature_url(bucket, key, image_size)
print(signature_url)

서명 된 URL을 사용하여 S3에 업로드
curl "署名付きURL" --upload-file /path/to/hoge.png

이미지 파일 업로드를 확인한 경위



현재 개발중인 블로그 서비스(ALIS)에서는 아래와 같이 직접 Lambda를 통해 이미지 파일을 업로드하고 있습니다.


다만, 상기의 구성의 경우, 구현은 간단합니다만 Lambda payload 제한 (6MB) 가 있기 (위해)때문에, 6MB 보다 큰 데이터를 취급할 수 없습니다 정도가 한계). 더 큰 이미지 파일을 다루고 싶은 요구 사항이 나왔기 때문에, Lambda를 통하지 않는 패턴으로의 검증을 실시했습니다.

조심한 것


  • 사용자가 업로드할 수 있는 객체 키를 제한할 수 있음
  • 업로드할 수 있는 파일 크기를 제한할 수 있음

  • 이것들은 소스 코드에 기재되어 있는 대로가 됩니다만 generate_presigned_urlParams 로 대응할 수 있었습니다.
    또, 이번의 경우, S3 에는 put_object 로 처리하고 있기 (위해)때문에, Request Headers로 설정할 수 있는 항목 그렇다면 제한등을 걸 수 있을까 생각합니다 (시험하지 않습니다,,).

    어리석은 곳



    generate_presigned_url 을 이용했을 때, ContentLength 를 지정해도 파일 사이즈의 제한이 효과가 없는 이벤트가 발생했습니다. 원인은 서명 버전의 지정 실수로, 도쿄 리전의 경우, 디폴트는 서명 버전 2 이며,
    지정해야 할 서명 버전 4가 설정되지 않았기 때문입니다.

    이러한 이유로 도쿄 지역을 사용하는 경우 아래와 같이 Config에서 서명 버전을 명시 적으로 설정해야했습니다.
    s3_cli = boto3.client('s3', config=Config(signature_version='s3v4'), region_name='ap-northeast-1')
    

    기타 파일 업로드 방법



    상기 이외에도 generate_presigned_url 을 이용하는 대신 generate_presigned_post 을 이용하는 방법이 있습니다.
    이 방법의 경우, POST 정책 을 이용할 수 있기 (위해)때문에, content-length-range 라고 말한, PUT 의 리퀘스트 (generate_presigned_url 를 이용한 경우)에서는 실현할 수 없는 제한의 부여가 가능합니다.

    요약



    generate_presigned_url 을 이용할지 generate_presigned_post 를 이용하는지는 제한하고 싶은 내용으로 결정하는 것이 좋을지도 모릅니다. 특히 제한하고 싶은 것으로 차이가 없으면, 프론트의 구현이 심플해지는 generate_presigned_url 가 추천입니다.

    좋은 웹페이지 즐겨찾기