HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/thread-self/root/opt/mistral/app.py
"""Simple Flask web interface for Mistral OCR

Features
--------
* Upload an arbitrary number of image files via browser (multi‑file input).
* Each image is sent to Mistral’s OCR endpoint (`https://api.mistral.ai/v1/ocr`).
* OCR output is written to `results/<original‑name>.json` (one JSON file per image).
* Uploaded images are saved in `uploads/` for traceability.

Prerequisites
-------------
$ pip install flask requests python-dotenv

You also need your Mistral API key available as an environment variable:

$ export MISTRAL_API_KEY="sk‑..."

Run the app locally on http://127.0.0.1:5000/:

$ python app.py
"""

import base64
import json
import mimetypes
import os
import uuid
from pathlib import Path

import requests
from flask import Flask, render_template_string, request, send_from_directory

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
MISTRAL_API_KEY = os.getenv("MISTRAL_API_KEY")
if not MISTRAL_API_KEY:
    raise EnvironmentError("Please set the MISTRAL_API_KEY environment variable")

UPLOAD_DIR = Path("uploads")
RESULT_DIR = Path("results")
UPLOAD_DIR.mkdir(exist_ok=True)
RESULT_DIR.mkdir(exist_ok=True)

HTML_FORM = """
<!doctype html>
<title>Mistral OCR Uploader</title>
<h1>Upload image(s) for OCR</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="images" multiple accept="image/*">
  <input type="submit" value="Upload">
</form>
{% if results %}
<h2>Processed Files</h2>
<ul>
  {% for name in results %}
    <li><a href="{{ url_for('download_result', filename=name) }}">{{ name }}</a></li>
  {% endfor %}
</ul>
{% endif %}
"""

app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 100 * 1024 * 1024  # 100 MB per request

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def _image_to_data_url(path: Path) -> str:
    """Return a data: URL containing base64‑encoded image data."""
    mime_type, _ = mimetypes.guess_type(path)
    with path.open("rb") as f:
        encoded = base64.b64encode(f.read()).decode()
    return f"data:{mime_type or 'application/octet-stream'};base64,{encoded}"


def _call_mistral_ocr(image_path: Path) -> dict:
    """Invoke Mistral OCR and return the parsed JSON response."""
    url = "https://api.mistral.ai/v1/ocr"
    headers = {
        "Authorization": f"Bearer {MISTRAL_API_KEY}",
        "Content-Type": "application/json",
    }
    payload = {
        "model": "mistral-ocr-latest",
        "document": {
            "type": "image_url",
            "image_url": _image_to_data_url(image_path),
        },
    }
    resp = requests.post(url, headers=headers, json=payload, timeout=120)
    resp.raise_for_status()
    return resp.json()

# ---------------------------------------------------------------------------
# Routes
# ---------------------------------------------------------------------------

@app.route("/", methods=["GET"])
def index():
    return render_template_string(HTML_FORM, results=[])


@app.route("/upload", methods=["POST"])
def upload():
    files = request.files.getlist("images")
    processed = []
    for fs in files:
        if not fs.filename:
            continue
        unique_name = f"{uuid.uuid4().hex}_{fs.filename}"
        save_path = UPLOAD_DIR / unique_name
        fs.save(save_path)
        try:
            ocr_data = _call_mistral_ocr(save_path)
            result_name = f"{save_path.stem}.json"
            (RESULT_DIR / result_name).write_text(
                json.dumps(ocr_data, ensure_ascii=False, indent=2),
                encoding="utf-8",
            )
            processed.append(result_name)
        except Exception as exc:
            print(f"[ERROR] {fs.filename}: {exc}")
    return render_template_string(HTML_FORM, results=processed)


@app.route("/results/<path:filename>")
def download_result(filename):
    return send_from_directory(RESULT_DIR, filename, as_attachment=True)


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)