作るもの
S3からエクセルファイルを取得し、
その内容をPDFに変換し、
そのPDFをS3に保存するLambda関数
PDF操作にはLibreOfficeを使用
前提
- aws samを使って構築していく
- CLIを使えるようにしておく
- init samでhello worldのテンプレートが実行できる状態にしておく
開発
template
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  convert_excel_into_pdf
Globals:
  Function:
    Timeout: 900 # ここまで増やす必要ないと思うが念の為
    MemorySize: 256 # LibreOfficeは結構メモリ使うので上げとく。128じゃ足りないかも。
    Tracing: Active
  Api:
    TracingEnabled: true
Parameters:
  BucketName:
    Type: String
    Default: 'my-bucket'
  ConvertExcelIntoPdfFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: convert_excel_into_pdf/
      Architectures:
        - x86_64
      Environment:
        Variables:
          BUCKET_NAME: !Ref BucketName
      # コンテナイメージをDockerで手動作成したいのでパッケージタイプはImage
      PackageType: Image
      Policies:
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
    Metadata:
      Dockerfile: Dockerfile
      DockerContext: ./convert_excel_into_pdf
      DockerTag: python3.8-v1
DockerFile
Dockerfile
FROM public.ecr.aws/lambda/python:3.8
RUN yum -y install curl wget tar gzip zlib freetype-devel
RUN yum -y install libxslt \
    gcc \
    ghostscript \
    lcms2-devel \
    libffi-devel \
    libjpeg-devel \
    libtiff-devel \
    libwebp-devel \
    make \
    openjpeg2-devel \
    sudo \
    tcl-devel \
    tk-devel \
    tkinter \
    which \
    xorg-x11-server-Xvfb \
    zlib-devel \
    java \
    ipa-gothic-fonts ipa-mincho-fonts ipa-pgothic-fonts ipa-pmincho-fonts \
    && yum clean all
# LibreOfficeツールをダウンロード
RUN wget http://download.documentfoundation.org/libreoffice/stable/7.5.3/rpm/x86_64/LibreOffice_7.5.3_Linux_x86-64_rpm.tar.gz
RUN tar -xvzf LibreOffice_7.5.3_Linux_x86-64_rpm.tar.gz
RUN cd LibreOffice_7.5.3.2_Linux_x86-64_rpm/RPMS; yum -y localinstall *.rpm;
RUN yum -y install cairo
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.lambda_handler" ]
Lambda関数
app.py
import os
import subprocess
import boto3
s3 = boto3.resource("s3")
output_bucket = os.getenv("BUCKET_NAME")
def lambda_handler(event, context):
    input_bucket = os.getenv("BUCKET_NAME")
    input_key = "output.xlsx"
    in_bucket = s3.Bucket(input_bucket)
    # エクセルファイルを取得
    file_path = "/tmp/" + input_key
    in_bucket.download_file(input_key, file_path)
    # LibreOfficeを使ってPDF変換
    proc = subprocess.run(
        "/opt/libreoffice7.5/program/soffice --headless --norestore --invisible --nodefault --nofirststartwizard --nolockcheck --nologo --convert-to pdf:writer_pdf_Export --outdir /tmp {}".format(
            file_path
        ),
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    print("STDOUT: {}".format(proc.stdout))
    print("STDERR: {}".format(proc.stderr))
    key_list = input_key.split(".")
    pdf_path = file_path.replace(key_list[-1], "pdf")
    # PDFファイルをアップロード
    if not os.path.exists(pdf_path):
        print("The PDF file({}) cannot be found".format(pdf_path))
        return
    print("PDF: {}".format(pdf_path.replace("/tmp/", "")))
    print("Size: {}".format(os.path.getsize(pdf_path)))
    data = open(pdf_path, "rb")
    out_bucket = s3.Bucket(output_bucket)
    out_bucket.put_object(Key=pdf_path.replace("/tmp/", ""), Body=data)
    data.close()
    return {"statusCode": 200, "message": "PDF変換完了"}
参考
