70 lines
2.3 KiB
Python
70 lines
2.3 KiB
Python
from fastapi import FastAPI, UploadFile, File, Request
|
|
from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
from fastapi.staticfiles import StaticFiles
|
|
from markitdown import MarkItDown
|
|
from markitdown._stream_info import StreamInfo
|
|
import io, os, mimetypes
|
|
|
|
app = FastAPI(title="MarkItDown Converter")
|
|
templates = Jinja2Templates(directory="templates")
|
|
|
|
# markitdown supports: PDF, DOCX, PPTX, XLSX, HTML, CSV, JSON, XML,
|
|
# images (with OCR via LLM), audio, ZIP, EPUB, YouTube URLs, Wikipedia, etc.
|
|
ALLOWED_EXTENSIONS = {
|
|
".pdf", ".docx", ".doc", ".pptx", ".ppt", ".xlsx", ".xls",
|
|
".html", ".htm", ".csv", ".json", ".xml", ".epub",
|
|
".txt", ".md", ".rst", ".zip", ".msg",
|
|
".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp",
|
|
".mp3", ".wav", ".m4a",
|
|
}
|
|
|
|
MAX_SIZE_MB = 50
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
async def index(request: Request):
|
|
return templates.TemplateResponse("index.html", {"request": request})
|
|
|
|
|
|
@app.post("/convert")
|
|
async def convert(file: UploadFile = File(...)):
|
|
# Validate extension
|
|
_, ext = os.path.splitext(file.filename or "")
|
|
ext = ext.lower()
|
|
if ext not in ALLOWED_EXTENSIONS:
|
|
return JSONResponse(
|
|
{"error": f"Unsupported file type: '{ext}'. Supported: {', '.join(sorted(ALLOWED_EXTENSIONS))}"},
|
|
status_code=400
|
|
)
|
|
|
|
# Read into memory
|
|
data = await file.read()
|
|
size_mb = len(data) / (1024 * 1024)
|
|
if size_mb > MAX_SIZE_MB:
|
|
return JSONResponse(
|
|
{"error": f"File too large ({size_mb:.1f} MB). Max: {MAX_SIZE_MB} MB"},
|
|
status_code=413
|
|
)
|
|
|
|
try:
|
|
md = MarkItDown()
|
|
stream = io.BytesIO(data)
|
|
mime = mimetypes.types_map.get(ext, "application/octet-stream")
|
|
result = md.convert_stream(
|
|
stream,
|
|
stream_info=StreamInfo(
|
|
mimetype=mime,
|
|
extension=ext,
|
|
filename=file.filename,
|
|
)
|
|
)
|
|
markdown_text = result.text_content or ""
|
|
return JSONResponse({
|
|
"markdown": markdown_text,
|
|
"filename": file.filename,
|
|
"size_kb": round(len(data) / 1024, 1),
|
|
"chars": len(markdown_text),
|
|
})
|
|
except Exception as e:
|
|
return JSONResponse({"error": f"Conversion failed: {str(e)}"}, status_code=500) |