API Gatewayで画像を受け取ったり返したりするサンプル

AWSのAPI GatewayとLambdaでREST APIを構築するケースは多いかと思います。 その際に画像を扱う上でいくつかハマるポイントがあったので共有します。 Lambdaプロキシ統合を用いたAPIを前提とします。

バイナリメディアタイプを追加する

AWS - REST API のバイナリメディアタイプの使用によると、以下のように書かれています。

AWS Lambda プロキシ統合のバイナリペイロードを処理するには、関数のレスポンスを base64 でエンコードする必要があります。また、API の binaryMediaTypes を設定する必要があります。API の binaryMediaTypes 設定は、API がバイナリデータとして扱うコンテンツタイプのリストです。バイナリメディアタイプの例には、image/png または application/octet-stream が含まれます。ワイルドカード文字 () を使用して、複数のメディアタイプを対象にすることができます。例えば、/* にはすべてのコンテンツタイプが含まれます。

ここでいうバイナリメディアタイプは、API Gatewayのコンソール画面から設定できます。 左メニューから[設定]を選択し、画面下部の「バイナリメディアタイプ」に扱いたいメディアタイプを記載しましょう。 ※画像全般を扱う場合はimage/*と入れると良いです

api_binary_media_type.png

画像を受け取るAPI

画像を受け取るAPIについては特別な処理は必要ないです。 Lambda上では、送られてきた画像(バイナリ)はbase64にエンコードされた状態でevent.bodyに格納されているので、デコードした上で処理を行いましょう。

実際にはS3のバケットに格納するか、DBに格納するかの二択だと思います。

exports.handler = async (event, context) => {
  try {
    // リクエストボディに設定された画像データはBase64エンコードされているので、デコードする
    const image = Buffer.from(event.body, 'base64');
    
    if(image) {
      
      // imageをS3に入れたり、DBに入れたり・・・

      return {
        statusCode: 200,
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          result: true,
        })
      };
    }
  } catch (e) {
    return {
      statusCode: 500,
      headers: {
        "Content-Type": "application/json"
      },
      body: e.message
    }
  }
};

画像を返却するAPI

画像を返却するAPIのLambdabase64でエンコードした状態でレスポンスボディに格納する必要があります。 こちらも、画像の実体をどこで持つかによって取得方法は変わってきますが、概ね以下のようなレスポンスのイメージです。

exports.handler = async (event, context) => {
  try {
    // imageは実際にはS3から取得したり、DBから取得したりする
    const imaeg = null;
    return {
      statusCode: 200,
      headers: {
        "Content-Type": "image/png"
      },
      body: image.toString("base64")
    };
  } catch (e) {
    return {
      statusCode: 500,
      headers: {
        "Content-Type": "application/json"
      },
      body: e.message
    }
  }
};

あとはAPIを叩くだけなのですが、Acceptをヘッダにつけて、値を目的の画像のメディアバイナリタイプとしましょう。 これを忘れると正常に画像が取得できません。

まとめ

今回はAPI GatewayLambdaを用いて作成するREST APIにおいて、画像(バイナリ)を扱う際の実装の簡単なサンプルを紹介しました。 忘れがちなのがAPI Gateway側で「メディアバイナリタイプ」を設定し忘れていたり、取得時にAcceptをヘッダにつけていなかったり等です。 この場合、ログを見てもLambdaは正常に動いており、そこから先のAPI Gatwayとのデータの授受で失敗しているのでなかなか気づきにくいです。

今回の内容が役立ちましたら幸いです。

SNSでシェアする