LoginSignup
2
1

More than 1 year has passed since last update.

AWS LambdaでqrcodeとPillowを利用したQRコード生成(カスタムレイヤーを利用)

Last updated at Posted at 2021-06-19

AWS Lambdaでqrcodeとpillowを利用しQRコードを生成してみます。
実装自体は簡単なのですがLambadaのカスタムレイヤーの作成に手こずりました。
LambdaのランタイムにはPython3.8を利用します。

利用ライブラリについて (qrcode/pillow)

qrcodeとpillowはLambda標準ライブラリに含まれていないのでカスタムレイヤーとして追加します。
pillowはOS依存があるのでレイヤー用のZipを作成する際はLambdaのPython実行環境と同じOSで作成する必要があります。
実行環境は言語やバージョンによって異なります。詳細は以下リンク先を参照ください。
Lambda ランタイム

今回はAWS SAM用に用意されたDockerコンテナを利用してレイヤーを作成します。

事前準備 Docker

今回はCloud9上でレイヤーの作成を行います。
Cloud9では標準でDockerがインストールされているはずです。以下で確認します。

# バージョン確認
docker --version
# サービスの実行状態確認
sudo docker info
# 自分がDockerグループに所属しているか確認。「docker」が含まれていればOK.
groups
# 動作確認
docker run hello-world

カスタムレイヤーの作成

以下の構造でフォルダと「requirements.txt」を作成します。

├── requirements.txt
└── python/
    └── lib/
        └── python3.8/
            └── site-packages/

requirements.txtには必要なライブラリを記載します。今回は以下の2つです。

qrcode
Pillow

準備したフォルダにライブラリをインストールします。

docker run -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.8" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.8/site-packages/; exit"

インストールしたライブラリをZIP化します。

zip -r qrcodelibs.zip python > /dev/null

レイヤーを更新します。

aws lambda publish-layer-version --layer-name qrcodelibs --description "qrCodelibs" --zip-file fileb://qrcodelibs.zip --compatible-runtimes "python3.8"

作成したレイヤーを使用するようにLamba関数を更新します。
レイヤーのARNとLambda関数名は環境に合わせて変更してください。

aws lambda update-function-configuration --layers arn:aws:lambda:us-east-1:xxx:layer:qrcodelibs:1 --function-name my-function

QRコードの生成(SVG形式)

QRコードを生成するLambda関数です。
Lambdaプロキシ統合の場合はBase64での返却が必須なので
生成したデータをBase64形式にしてから送信します。

import io
import qrcode
import base64
import qrcode.image.svg

def lambda_handler(event, context):

    encoded_image = make_base64_svg('qrtest')

    return {
        "statusCode": 200,
        "headers": {"Content-Type": 'image/svg+xml'},
#        "headers": {"Content-Type": "image/png"},
        # Lambdaプロキシ統合の場合はBase64での返却が必須
        "isBase64Encoded": True,
        "body": encoded_image
    }

def make_base64_svg(data):
    qr = qrcode.QRCode(
        box_size=400,
        border=2,
    )
    qr.add_data(data)
    qr.make(fit=True)
    img = qr.make_image(image_factory=qrcode.image.svg.SvgPathImage,fill_color="black", back_color="white")
    buffered = io.BytesIO()
    img.save(buffered)
    buffered.flush()
    base64str = base64.b64encode(buffered.getvalue()).decode("utf-8")

    return base64str 

QRコードの生成(PNG形式)

PNG形式の場合は下記のようになります。フォーマット指定が変更になるだけです。

def make_base64_png(data):
    qr = qrcode.QRCode()
    qr.add_data(data)
    qr.make()
    img = qr.make_image()

    buffered = io.BytesIO()
    img.save(buffered, format="PNG")
    base64str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return base64str

APIGatewayで画像返却する際の注意点

AWS Lambda プロキシ統合のバイナリペイロードを処理するには、関数のレスポンスを base64 でエンコードする必要があります。
また、API の binaryMediaTypes を設定する必要があります。

 参考

以上

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1