英語: How to get the uploaded file path and processing its file in Streamlit
モチベーション
Streamlit は Python code のみで簡単かつ高速に Web アプリを作成できる強力なパッケージ。
Streamplit で作られた Web アプリ経由でファイルをアップロードして、そのファイルを処理したい際の具体的な実現方法がなかったので備忘録がてら残しておく。
PDF ファイルをアップロードして、画像に変換する Web アプリ
具体的に例を交えつつ説明する。
Streamlit を使って、PDF ファイルをアップロードしてアップロードされた PDF ファイルを画像化するアプリを作成する。
今回は、Belval/pdf2image という PDF パッケージを使用する。
このパッケージは処理したい PDF のファイルパスを要求するインターフェースなので今回の実例に沿っていてわかりやすい。
ローカルマシンは MacOS を想定しており、pdf2image
はpoppler の事前インストールが必須。
完成形のスクリーンショット
GitHub でもコードを公開しておきました。
hurutoriya/streamlist-file-uploader-example
デモ動画はこちら
Makefile
Makefile は依存パッケージを事前インストールするために採用
install:
brew install poppler
poetry install
run:
poetry run streamlit run streamlit_pdf_uploader/main.py
Poetry for package management
環境構築は poetry を使っています。
[tool.poetry]
name = "streamlit-pdf-uploader"
version = "0.1.0"
description = ""
authors = [""]
[tool.poetry.dependencies]
python = "^3.8"
streamlit = "^0.84.0"
watchdog = "^2.1.3"
pdf2image = "^1.16.0"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Streamlit Python file
import base64
import tempfile
import streamlit as st
from pdf2image import convert_from_path
from pathlib import Path
def show_pdf(file_path:str):
"""Show the PDF in Streamlit
That returns as html component
Parameters
----------
file_path : [str]
Uploaded PDF file path
"""
with open(file_path, "rb") as f:
base64_pdf = base64.b64encode(f.read()).decode("utf-8")
pdf_display = f'<embed src="data:application/pdf;base64,{base64_pdf}" width="100%" height="1000" type="application/pdf">'
st.markdown(pdf_display, unsafe_allow_html=True)
def main():
"""Streamlit application
"""
st.title("PDF file uplodaer")
uploaded_file = st.file_uploader("Choose your .pdf file", type="pdf")
if uploaded_file is not None:
# Make temp file path from uploaded file
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
st.markdown("## Original PDF file")
fp = Path(tmp_file.name)
fp.write_bytes(uploaded_file.getvalue())
st.write(show_pdf(tmp_file.name))
imgs = convert_from_path(tmp_file.name)
st.markdown(f"Converted images from PDF")
st.image(imgs)
if __name__ == "__main__":
main()
Conclusion
これで、Streamlit 上でファイルをアップロードして、そのアップロードされたファイルに対する処理ができます。
画像や音声など色々応用先があるので便利そう。
動作が遅いという欠点はあれど、これだけ簡単に GUI を Python のみで構築できるのは驚き。
Protly Dash も 2 年ほど前に使ったことがあるけど、UI のライフサイクルや HTML を結構意識しないとかけなかったので辛かった記憶があるので、なおさら感動している。