APIGateway + Lambdaでbase64変換された画像ファイルをS3に保存する


やろうとしていること。

  1. API Gateway を使って POST リクエストを受け付けるエンドポイントを作成する。
  2. POST リクエストのボディには PNG 画像が base64 エンコードされた文字列が含まれる。
  3. 投げられたリクエストは lambda で処理される。
    • PNG 画像の base64 文字列は binary に変換
    • {自動作成したUUID}.pngという名前で s3 に保存

作業

s3 バケットを作成する。

  • aws のコンソール上からサービス-> s3 を選択
  • 適当な名前でバケットを作成する。
  • 今回は権限変更の必要なし。(バケットの内容を外部公開したいなら必要)
  • 作成したバケットの名前は覚えておく。

lambda でリクエストボディに入力された関数を作成する。

  • aws のコンソールの上からサービス-> Lambda を選択 -関数の作成ボタンから関数を作成する。
  • 下記内容を入力する。
    • 関数名 -> 適当
    • ランタイム -> python3.7
    • 実行ロール -> 基本的な Lambda アクセス権限で新しいロールを作成(あとで s3 にファイルをアップロードできるように権限の変更必要)
  • 関数の作成をクリック
  • ダッシュボードから自分が作成した関数名の関数を選択する。
  • 実行ロール項目に現在設定されているロール名が表示されているのでIAM コンソールで {自分が作成したロール名} ロールを表示します。をクリック
  • IAM のコンソールに移動するのでポリシーをアタッチしますをクリック
  • AmazonS3FullAccessを選択してポリシーのアタッチをクリック
  • 関数コードのに下記のようなコードを書く

import boto3
import base64
import uuid

def convert_b64_string_to_bynary(s):
    """base64をデコードする"""
    return base64.b64decode(s.encode("UTF-8"))

def lambda_handler(event, context):
    # requestbodeyの中のjsonはeventに辞書型に変化されて保存されている
    # なので、eventの中には {"mypng": "base64でエンコードされた文字列"}が入力される想定。
    base_64ed_image = event['mypng']
    # バケット作成を作成してbynary変換して保存する。
    s3 = boto3.resource('s3')
    bucket = s3.Bucket('<s3でバケットを作成したときにつけたファイル名>')
    bucket.put_object(
                    Key=f'{uuid.uuid4()}.png',
                    Body=convert_b64_string_to_bynary(base_64ed_image),
                    ContentType='image/png')
    # とりあえずOKを返す。
    return {'statusCode': 200}

  • 右上の保存ボタンを押す。

API エンドポイントを作成する。

  • aws のコンソールの上からサービス-> API gateway を選択
  • APIの作成ボタンからAPIを作成する。
  • 適当な API 名をつけて、あとはそのままで API の作成ボタンを押す。
  • 自分が作成した API を選択し、アクションボタンからメソッドの作成を選択し、POST メソッドを追加
    • 統合タイプ -> Lambda 関数
    • Lambda 関数 -> 先ほど作成した関数の関数名を入力
  • 保存する。

API のテスト

  • 先の手順で作成したメソッドを選択するとテストボタンがあるのでリクエストボディに値を入力してテストしてみる
{
  "mypng": "<base64エンコードされた文字列>"
}
  • png ファイルを base64 に変換する python スクリプトは下記の通り
# これでファイルを文字列で読み取れるのでテキストに書き込むなり標準入力に出力するなりする。
def convert_file_to_b64_string(file_path):
    """ファイルをbase64にエンコードする"""
    with open(file_path, "rb") as f:
        return base64.b64encode(f.read()).decode("UTF-8")

API のデプロイ(外部公開)

  • aws のコンソールの上からサービス-> API gateway を選択
  • 作成したAPIを選択
  • アクションボタンからAPIのデプロイを選択
    • デプロイされるステージ -> 新しいステージ
    • ステージ名 -> 任意のアルファベットとハイフンの組み合わせ
  • デプロイボランを押す。
  • コンソールに表示されたURLにデプロイ(外部公開)されている。