Azure FunctionsでOffice系ファイルを処理するエンドポイントを作成する

本ガイドでは、Azure Functionsを用いてPowerPoint(PPTX)ファイルをPDF形式に変換するプロセスを詳細に説明します。

本手法では、オープンソースソフトウェアであるLibreOfficeをDockerイメージに導入し、サーバレスアーキテクチャ上で効率的にファイル変換を行います。

この記事を通じて、ユーザーは自動化されたファイル処理の実装を手軽に行えるようになり、ビジネスプロセスの効率化を図ることが可能になります。最終的には、より効果的なドキュメント管理と運用が実現できることを目指しています。

方法

Office系ファイルを処理するためには、専用のソフトウェアがインストールされている必要があります。

Azure FunctionsでPowerPointやExcelファイルを処理するためには、オープンソースソフトウェアであるLibreOfficeを含むDockerイメージを利用することが有効な方法となります。

以下に、LibreOfficeを含む既存のDockerイメージを、Azure Functionsに適用する方法について説明します。

作業手順

プログラムの準備

Functionsにデプロイするプログラムを準備します。

import azure.functions as func
import logging
import re  
import os
import base64
import json
import subprocess
import tempfile
from io import BytesIO
from pptx import Presentation 

app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)


def convert_pptx_to_pdf(pptx_path, pdf_path):
    # LibreOfficeを使用してPPTXをPDFに変換
    convert_command = [
        "libreoffice", "--headless", "--convert-to", "pdf", pptx_path, "--outdir", os.path.dirname(pdf_path)
    ]
    subprocess.run(convert_command, check=True)


@app.route(route="convert_with_notes")
def convert_with_notes(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('PPTX to PDF conversion and notes extraction function triggered.')

    try:
        # リクエストからBase64エンコードされたpptxファイルを取得
        req_body = req.get_json()
        encoded_pptx = req_body.get('pptx_base64')
        if not encoded_pptx:
            return func.HttpResponse("pptx_base64 field is missing.", status_code=400)

        # Base64デコードして一時PPTXファイルとして保存
        pptx_data = base64.b64decode(encoded_pptx)
        with tempfile.NamedTemporaryFile(delete=False, suffix=".pptx") as pptx_file:
            pptx_file.write(pptx_data)
            pptx_path = pptx_file.name

        # PDFファイルの一時パスを設定
        pdf_path = pptx_path.replace(".pptx", ".pdf")

        # PPTXをPDFに変換
        convert_pptx_to_pdf(pptx_path, pdf_path)

        # PDFファイルをBase64エンコード
        with open(pdf_path, "rb") as pdf_file:
            pdf_data = pdf_file.read()
        pdf_base64 = base64.b64encode(pdf_data).decode("utf-8")

        # 一時ファイルの削除
        os.remove(pptx_path)
        os.remove(pdf_path)

        # JSONレスポンスでPDFとノート情報を返す
        response_data = {
            "pdf_base64": pdf_base64
        }
        return func.HttpResponse(
            body=json.dumps(response_data),
            status_code=200,
            mimetype="application/json"
        )

    except Exception as e:
        logging.error(f"An error occurred: {str(e)}")
        return func.HttpResponse(
            f"An error occurred: {str(e)}",
            status_code=500
        )

base64形式でのPPTXのファイルを送信し、base64形式のpdfファイルをレスポンスで取得します。

request

{
    "pptx_base64": ""
}

Dockerfileの準備

まず、LibreOfficeが含まれるDockerイメージを作成します。Azure FunctionsのイメージにLibreOfficeを追加するDockerFileを作成します。

# Azure FunctionsのPythonベースイメージを使用
FROM mcr.microsoft.com/azure-functions/python:4-python3.11

# LibreOfficeのインストール
RUN apt-get update && \
    apt-get install -y libreoffice fonts-noto-cjk ttf-mscorefonts-installer && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 必要なPythonライブラリのインストール(例:pandas, numpyなど)
COPY ./OfficeFunctions/requirements.txt /
RUN pip install --no-cache-dir -r /requirements.txt



# Pythonプログラムや関数コードをコンテナ内にコピー
COPY ./OfficeFunctions /home/site/wwwroot

DockerFileは次のように配置します。

FunctionsのベースイメージはDocker Hubから確認できます。

https://hub.docker.com/r/microsoft/azure-functions-python

Azure Container Registory(ACR)のデプロイとイメージのプッシュ

「コンテナーレジストリ」と検索してサービスを作成します。

ACRの1日あたりのコストは次の通りです*1。本検証ではBasicを選択しますが、Private Endpointを適用する場合はPremiumプランを選択する必要があります。

Basic 標準 Premium
日額 ¥25.570 ¥102.310 ¥255.790

以下のコマンドを実行して、ACRにLibreOfficeの入ったイメージをビルド&プッシュします。

az account set --subscription [サブスクリプションID]
az acr login --name [ACR名]

cd [Dockerfileの存在するディレクトリ]

docker build -t [ACR名].azurecr.io/libreoffice:latest .
docker push [ACR名].azurecr.io/libreoffice:latest

libreofficeのコンテナがデプロイされたことが分かります。

エンドポイント作成作業完了後にローカル環境でプログラムや構成の変更があった場合は、同じくdocker buildとdocker pushを行って、Functionsを再起動します。

Azure Functionsのデプロイ

ACRのデプロイ後、以下のコマンドでAzure Functionsをデプロイしていきます。Japan EastでB1プランでデプロイしておきます。

az functionapp plan create --resource-group [リソースグループ名] --name [任意のApp Service Plan名] --location "japaneast" --is-linux --sku B1
az storage account create --name [任意のStorage Account名] --location japaneast --resource-group [リソースグループ名] --sku Standard_LRS
az functionapp create --name [任意のFunction名] --storage-account [Storage Account名] --resource-group [リソースグループ名] --plan [App Service Plan名] --functions-version 4 --deployment-container-image-name [ACR名].azurecr.io/libreoffice:latest

デプロイした関数アプリの[概要]ページのプロパティタブから、適用されるコンテナーイメージ名を確認できます。

Azure Functionsへのイメージのプッシュ

Azure Functionsに対してイメージをプッシュするための用意をします。

まずは、次のコマンドを実行し、ユーザーIDとパスワードを利用した認証を使用する準備をします。

az acr update -n [ACR名] --admin-enabled true --resource-group [リソースグループ名]
az acr credential show --name [ACR名] --resource-group [リソースグループ名]

次のようなレスポンスが返ってくるので、usernameとpassword(上のほう)をコピーしておきます。

{
  "passwords": [
    {
      "name": "password",
      "value": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    },
    {
      "name": "password2",
      "value": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    }
  ],
  "username": "[ユーザー名(※ACRと同名)]"
}

次のコマンドで、Azure Functionsの環境変数を設定します。

az functionapp config container set --name [Function名] --resource-group [リソースグループ名]  --docker-custom-image-name [ACR名].azurecr.io/libreoffice:latest  --docker-registry-server-url https://[ACR名].azurecr.io  --docker-registry-server-user [取得したユーザー名] --docker-registry-server-password [取得したパスワード]

[デプロイ]-[デプロイセンター]からログのタブを開くと、処理のログを確認できます。

latest Pullingのログがあれば成功です。概ね5分単位でコンテナーのプル処理のバッチが走っているようです。失敗している場合はDockerApiException: Docker API responded with status code=InternalServerErrorなどが表示されるため、ACR名、ID、パスワードなどを確認してください。Functionsを再起動することで再度プルの処理が走ります。

成功すると、概要ページに関数が表示されます。

関数の利用

以下のコードで、関数にリクエストを送信して結果を取得します。

LibreOfficeを使用しているため、互換性の問題から若干図形や文字がずれることがありますが、変換したpdfファイルをダウンロードすることができます。

import requests
import base64
import json

url = ""
pptx_file_path = "XXX.pptx"


# PPTXファイルをBase64にエンコード
with open(pptx_file_path, "rb") as file:
    pptx_base64 = base64.b64encode(file.read()).decode("utf-8")


# レスポンスの処理
if response.status_code == 200:
    response_data = response.json()
    
    # PDFファイルのデコードと保存
    pdf_data = base64.b64decode(response_data["pdf_base64"])
    with open("converted_presentation.pdf", "wb") as pdf_file:
        pdf_file.write(pdf_data)
    print("PDFファイルが 'converted_presentation.pdf' に保存されました。")

else:
    print(f"Error: {response.status_code}")
    print(response.text)

LibreOfficeにPPTXファイルからPDFファイルを作成させた場合、以下のような文字ずれが発生しました。

元ファイル

PDF化した場合(LibreOffice)

おわりに

本ガイドでは、Azure Functionsを利用してPowerPointファイルをPDFに変換するための、具体的な手順を解説しました。

LibreOfficeをDockerイメージとして取り込み、サーバレス環境でのファイル変換処理を効率的に行う方法を紹介しました。これにより、Office系ファイルの自動処理が可能となり、ファイルの変換や配布、共有にかかる手間や時間を削減できます。

ただしオープンソースであるLibreOfficeと、ライセンスが必要なMicrosoftOfficeでは互換性の課題があり、完全な変換ができない点には注意が必要です。

このガイドが皆様のプロジェクトに役立ち、効果的なファイル処理の一助となれば幸いです。

*1:価格は記事執筆時のものです

執筆担当者プロフィール
西野 佑基

西野 佑基(日本ビジネスシステムズ株式会社)

機械学習系ソリューション開発、業務Webアプリ開発、開発環境自動化などを担当。

担当記事一覧