sábado, 11 de octubre de 2025

WEBPROPv2 (XII). Mostrar ficheros en un control FastHTML

 Veamos el código que ejecuta en python  un uvicorn y muestra el fichero que le decimos:

El truco está en utilizar libreoffice para transformar los ficheros de ofimática ( ods,odt, xls,xlsx, doc,docx ..) a html y mostrar el html generado.

Si el fichero es grande puede enlentecer mucho la carga, conversión y muestra

import base64
import mimetypes
from fasthtml import common as fh
import uvicorn
from pathlib import Path
import subprocess
import shutil


app = fh.FastHTML()



def convertir_a_html(path: Path) -> Path | None:
    """Convierte el archivo a HTML usando LibreOffice y devuelve la ruta resultante."""
    output_dir = Path("/tmp")
    result = subprocess.run(
        ["libreoffice", "--headless", "--convert-to", "html", str(path), "--outdir", str(output_dir)],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    if result.returncode == 0:
        html_file = output_dir / (path.stem + ".html")
        if html_file.exists():
            return html_file
    return None

def generar_viewer(path: Path):
    mime_type, _ = mimetypes.guess_type(str(path))
    if not mime_type:
        mime_type = "application/octet-stream"

    data = path.read_bytes()
    b64 = base64.b64encode(data).decode("utf-8")

    # Imágenes
    if mime_type.startswith("image/"):
        return fh.Img(src=f"data:{mime_type};base64,{b64}", cls="img-fluid rounded shadow", alt=path.name)

    # PDF
    if mime_type == "application/pdf":
        return fh.Iframe(src=f"data:{mime_type};base64,{b64}",
                         style="width:100%; height:90vh;",
                         cls="border rounded shadow-sm",
                         title=path.name)

    # Texto
    if mime_type.startswith("text/"):
        content = data.decode("utf-8", errors="ignore")
        return fh.Pre(content, cls="bg-light p-3 border rounded")

    # ODS / XLSX / DOCX — convertir a HTML
    convertible_types = {
        "application/vnd.oasis.opendocument.spreadsheet",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        "application/vnd.oasis.opendocument.text",
        'application/msword',
        'application/vnd.ms-excel',
    }
    if mime_type in convertible_types:
        html_file = convertir_a_html(path)
        if html_file:
            html_content = html_file.read_text(encoding="utf-8", errors="ignore")
            return fh.Div(fh.NotStr(html_content), cls="border p-2 bg-white shadow-sm")

    # Otros: ofrecer descarga
    return fh.Div(
        fh.P("El archivo no puede mostrarse directamente en el navegador.", cls="text-muted"),
        fh.A("Descargar archivo", href=f"data:{mime_type};base64,{b64}",
             download=path.name, cls="btn btn-primary mt-3"),
        cls="text-center"
    )

@app.get("/mostrarfichero")
async def mostrar_fichero(req):
    path_param = req.query_params.get("pathfichero")
    if not path_param:
        return fh.Html(fh.Body(fh.H4("⚠️ Falta el parámetro 'pathfichero'")))
    path = Path(path_param)
    if not path.exists():
        return fh.Html(fh.Body(fh.H4(f"❌ Archivo no encontrado: {path_param}")))
    viewer = generar_viewer(path)
    return fh.Html(
        fh.Head(fh.Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css")),
        fh.Body(
            fh.Div(
                fh.H3(f"Mostrando: {path.name}", cls="text-center my-4"),
                viewer,
                cls="container"
            )
        )
    )

if __name__ == "__main__":
    print("🚀 Abre en el navegador: http://localhost:8000/mostrarfichero?pathfichero=/home/edu/kk/ODS01.ods")
    uvicorn.run(app, host="0.0.0.0", port=8000)


Y para ejecutarlo, tal como se dice en as últimas sentencias, ejecutamos el programa python desde visual studio code y en un navegador apuntamos a esa ruta donde en /home/kk/OSD01.ods está un fichero de hoja de cálculo

http://localhost:8000/mostrarfichero?pathfichero=/home/edu/kk/ODS01.ods


No hay comentarios :

Publicar un comentario