1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DockerとPythonでMarkItDownをブラウザ上で使えるようにしてみる

Last updated at Posted at 2024-12-27

はじめに

先日、Microsoftが「MarkItDown」というツールを公開しました。このツールは、あらゆるフォーマットのファイルをマークダウン形式に変換してくれるツールです。
https://github.com/microsoft/markitdown
READMEを見てみると、コマンドラインで動かすことが想定されている。

markitdown path-to-file.pdf > document.md
markitdown path-to-file.pdf -o document.md
cat path-to-file.pdf | markitdown

チームメンバー全員が使い易いように、WEBにファイルをアップロードすればマークダウン形式に変換してくれるアプリを作成してみる。

本題

今回はDockerで環境構築をして、PythonライブラリのFlaskを用いてMarkItDownツールをブラウザで使えるようにしてみたいと思います。
ファイル構造は以下。

.
└── markitdown-app-docker
    ├── app.py
    ├── Dockerfile
    ├── docker-compose.yml
    └── uploads/

Flaskで簡易的なアプリケーションを作成

以下のようにPythonライブラリのFlaskを利用して、簡易的なアプリケーションを作成しました。
アップロードしたファイルは一度UPLOAD_FOLDERに保存されます。(<-好み)
アップロードできるファイル拡張子をALLOWED_EXTENSIONSで制限しています。(<-好み)

app.py
from flask import Flask, request, render_template_string
import os
import subprocess
from markitdown import MarkItDown

app = Flask(__name__)

# アップロードされたファイルの保存先ディレクトリ
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'txt', 'html', 'docx', 'pdf', 'pptx', 'xlsm', 'csv', 'json', 'xml', 'zip'}  # マークダウンに変換したいファイル形式

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# アップロードされるファイルの拡張子をチェック
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # ファイルが選択されているかチェック
        if 'file' not in request.files:
            return 'No file part'
        file = request.files['file']
        if file.filename == '':
            return 'No selected file'

        # ファイルを保存
        if file and allowed_file(file.filename):
            filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
            file.save(filename)

            # markitdownツールでマークダウンに変換
            md = MarkItDown()
            md_render = md.convert(filename)
            md_content = md_render.text_content

            # 変換したマークダウン内容を表示
            return render_template_string("""
                <h1>Markdown Output</h1>
                <pre>{{ md_content }}</pre>
                <br>
                <a href="/">Go back</a>
            """, md_content=md_content)

    return '''
    <!doctype html>
    <title>Upload File</title>
    <h1>Convert to Markdown</h1>
    <form method="post" enctype="multipart/form-data">
      <input type="file" name="file">
      <input type="submit" value="Upload">
    </form>
    '''

if __name__ == '__main__':
    app.run(host="0.0.0.0")

Dockerファイルの作成

Flaskで作成したアプリケーションを動作させるための環境をDockerで作成します。
基本的には、本家レポジトリのDockerfileを基に、少し変更しています。

Dockerfile
FROM python:3.13-slim-bullseye

USER root

# 作業ディレクトリを設定
WORKDIR /app

# markitdownツールのインストール(Node.jsが必要)
RUN apt-get update && apt-get install -y --no-install-recommends \
    ffmpeg \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN pip install markitdown Flask

# アプリケーションのコードをコピー
COPY ./app.py /app/

# アップロード用のディレクトリを作成
RUN mkdir -p /app/uploads

# ポート5000を開放
EXPOSE 5000

# Flaskアプリケーションを実行
CMD ["python", "app.py"]

docker-composeを使いたい人は、以下のようなyamlファイルを作成する。
他と被らないポートを設定してください(ここでは、5555番ポートを指定)

docker-compose.yml
services:
  app:
    build: .
    ports:
      - "5555:5000"
    volumes:
      - ./uploads:/app/uploads
    environment:
      - FLASK_ENV=development

完成

dockerコマンドでアプリケーションを立ち上げます。

docker compose up -d

その後、立ち上げたマシンにアクセスしてみる(例えば0.0.0.0:5555
すると、以下のような画面が立ち上がるので、ファイルを指定してアップロードすると、マークダウン形式に変換されたテキストが表示される。

image.png

終わりに

年末なので、元々目指していた形からはかなり簡易的な出来上がりになった。少なくとも、ドラッグアンドドロップでファイルのアップロードができるように改良したいところ。あとは、gpt-4oを使うmarkitdownや、リアルタイムにマークダウンを共同編集できたりすると嬉しいかも。今後、時間があれば改良していくかもしれないし、改良した際には記事もアップデートするかもしれない。良いお年を。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?