英語: 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 を想定しており、pdf2imagepoppler の事前インストールが必須。

完成形のスクリーンショット

get the uploaded file path in Streamlit

GitHub でもコードを公開しておきました。

hurutoriya/streamlist-file-uploader-example

デモ動画はこちら

Demo Movie in Youtube

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 を結構意識しないとかけなかったので辛かった記憶があるので、なおさら感動している。

Reference