pdf-api / app.py
habulaj's picture
Update app.py
837227b verified
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from playwright.async_api import async_playwright
from typing import Optional
import tempfile
import os
app = FastAPI()
# Configura CORS para permitir requisições do frontend
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Em produção, especifique os domínios permitidos
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Modelo para criar posts (gerar imagem a partir de HTML)
class PostRequest(BaseModel):
html: str
width: Optional[int] = 1080 # Largura padrão para posts (Instagram)
height: Optional[int] = 1350 # Altura padrão para posts (Instagram)
@app.get("/")
def greet_json():
return {"Hello": "World!"}
@app.post("/create-post")
async def create_post(request: PostRequest):
"""
Cria uma imagem a partir de HTML para posts.
Recebe HTML e retorna uma imagem PNG.
Exemplo de uso:
{
"html": "<div>Conteúdo do post</div>",
"width": 1080,
"height": 1350
}
"""
html_file = None
try:
# Garantir que o HTML está completo
html_content = request.html
# Se o HTML não tiver estrutura completa, adicionar
if "<!DOCTYPE" not in html_content and "<html" not in html_content:
html_content = f"""<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
{html_content}
</body>
</html>"""
# Criar arquivo temporário para o HTML
with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') as f:
f.write(html_content)
html_file = f.name
try:
# Usar Playwright Async API para renderizar HTML e gerar screenshot
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page(viewport={'width': request.width, 'height': request.height})
# Carrega o HTML do arquivo temporário
await page.goto(f'file://{html_file}')
# Espera o conteúdo carregar (especialmente imagens base64)
await page.wait_for_timeout(2000) # Aguarda 2 segundos para garantir que imagens e fontes carreguem
# Tira screenshot
screenshot_bytes = await page.screenshot(full_page=True, type='png')
await browser.close()
# Remove arquivo temporário
if os.path.exists(html_file):
os.unlink(html_file)
html_file = None
# Retorna a imagem
return Response(
content=screenshot_bytes,
media_type="image/png",
headers={
"Content-Disposition": "attachment; filename=post.png"
}
)
except Exception as e:
# Remove arquivo temporário em caso de erro
if html_file and os.path.exists(html_file):
os.unlink(html_file)
raise e
except Exception as e:
# Garantir limpeza do arquivo temporário
if html_file and os.path.exists(html_file):
try:
os.unlink(html_file)
except:
pass
raise HTTPException(status_code=500, detail=f"Erro ao gerar imagem do post: {str(e)}")