【Python】エクセルファイルをPDFに変換する

Uncategorized
711 words

エクセルファイルをPDFに変換するWEBサービスを作ります。

初めに

  • エクセルファイルアップロードすると、PDFファイルがダウンロードできるようにする。
  • Dockerfile を使ってデプロイを簡単にする。

ファイル構成

この3つで完結できます。

  • Dockerfile
  • main.py
  • requirements.txt

Dockerfile

PythonアプリケーションをDockerコンテナで実行する構成となっています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
FROM python:3.9-alpine3.12

WORKDIR /app
COPY . /app

RUN apk update

RUN apk add --no-cache --virtual .build-rundeps \
linux-headers \
build-base \
mariadb-connector-c-dev \
libxml2-dev \
libxslt-dev

RUN apk add --no-cache --virtual .libreoffice-rundeps \
libreoffice \
libreoffice-base \
libreoffice-lang-ja \
font-noto-cjk

COPY requirements.txt .
RUN pip install --upgrade pip
RUN python3 -m pip install --no-cache-dir -r requirements.txt

EXPOSE 80

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

Dockerfileの説明

ベースイメージの設定

1
FROM python:3.9-alpine3.12

Python 3.9 がインストールされた Alpine Linux 3.12 イメージをベースに使用します。

作業ディレクトリの設定

1
WORKDIR /app

作業ディレクトリをコンテナ内の app に設定します。

ファイルのコピー

1
COPY . /app

ホストマシンの現在のディレクトリの内容をコンテナ内の app にコピーします。

パッケージの更新

1
RUN apk update

Alpine Linux のパッケージリストを更新します。

依存パッケージのインストール(ビルド関連)

1
2
3
4
5
6
RUN apk add --no-cache --virtual .build-rundeps \
linux-headers \
build-base \
mariadb-connector-c-dev \
libxml2-dev \
libxslt-dev

ビルドに関連する依存パッケージをインストールします。

依存パッケージのインストール(LibreOffice関連)

1
2
3
4
5
RUN  apk add --no-cache --virtual .libreoffice-rundeps \
libreoffice \
libreoffice-base \
libreoffice-lang-ja \
font-noto-cjk

LibreOffice および関連パッケージをインストールします。

Python の依存ライブラリのインストール

1
2
3
COPY requirements.txt .
RUN pip install --upgrade pip
RUN python3 -m pip install --no-cache-dir -r requirements.txt

Python の依存ライブラリを requirements.txt ファイルに基づいてインストールします。

ポートの公開

1
EXPOSE 80

コンテナがポート 80 を外部に公開することを宣言します。

コンテナの起動コマンド

1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

コンテナが起動された際に実行されるコマンドを指定します。 uvicorn を使用して Pythonアプリケーション を ホスト:0.0.0.0ポート:80 で実行します。

main.py

  • FastAPI を使用してWebサービスを構築します。
  • ExcelファイルからPDFへの変換機能を提供します。
  • ユーザーはExcelファイルをアップロードし、変換されたPDFファイルを受け取ることができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import os
import shutil
import tempfile
import subprocess

from fastapi import FastAPI, UploadFile
from fastapi.responses import FileResponse

app = FastAPI()

def convertXlsx2Pdf(out_path, file_name):
cmd = []
cmd.append("libreoffice")
cmd.append("--headless")
cmd.append("--nologo")
cmd.append("--nofirststartwizard")
cmd.append("--convert-to")
cmd.append("pdf:calc_pdf_Export")
cmd.append("--outdir")
cmd.append(out_path)
cmd.append(file_name)

subprocess.run(" ".join(cmd), shell=True)

@app.post("/xlsx2pdf/")
async def create_upload_file(upload_file: UploadFile):

with tempfile.NamedTemporaryFile(delete=False) as temp_file:
shutil.copyfileobj(upload_file.file, temp_file)

convertXlsx2Pdf('./work', temp_file.name)

temp_file_name = os.path.basename(temp_file.name)
upload_file_name = upload_file.filename.rsplit('.', 1)[0]

return FileResponse(f'./work/{temp_file_name}.pdf', media_type='application/octet-stream', filename=f'{upload_file_name}.pdf')

requirements.txt

1
2
3
fastapi==0.104.0
uvicorn==0.23.2
python-multipart==0.0.6

実行

次のコマンドで Dockerイメージ を作成し、Dockerコンテナー を実行します。

1
2
docker build -t xlsx2pdf-image .
docker run -p 80:80 xlsx2pdf-image

Dockerコンテナーが起動したらブラウザーで http://localhost/docs を開くことができます。

  • XLSXファイルをアップロードする。
  • Execute で ファイルを POST する。
  • Download file で 変換されたPDFをダウンロードする。

あとは、自身のWEBサービスから呼んであげてください。

GitHub

https://github.com/noitaro/python-xlsx2pdf