thigas88 commited on
Commit
c103760
·
0 Parent(s):

first commit

Browse files
Files changed (7) hide show
  1. .gitignore +1 -0
  2. Dockerfile +32 -0
  3. Dockerfile.hf +39 -0
  4. README.md +46 -0
  5. main.py +65 -0
  6. requirements.txt +4 -0
  7. test.pdf +0 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ /api.log
Dockerfile ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Usar uma imagem base leve de Python
2
+ FROM python:3.11-slim
3
+
4
+ # Evitar a geração de arquivos .pyc e habilitar o log em tempo real
5
+ ENV PYTHONDONTWRITEBYTECODE 1
6
+ ENV PYTHONUNBUFFERED 1
7
+
8
+ # Instalar dependências do sistema, incluindo o compilador LaTeX
9
+ # texlive-latex-base contém o pdflatex básico
10
+ # texlive-fonts-recommended é necessário para fontes comuns
11
+ RUN apt-get update && apt-get install -y --no-install-recommends \
12
+ texlive-latex-base \
13
+ texlive-fonts-recommended \
14
+ texlive-latex-extra \
15
+ && apt-get clean \
16
+ && rm -rf /var/lib/apt/lists/*
17
+
18
+ # Definir diretório de trabalho
19
+ WORKDIR /app
20
+
21
+ # Instalar dependências Python
22
+ COPY requirements.txt .
23
+ RUN pip install --no-cache-dir -r requirements.txt
24
+
25
+ # Copiar o código da aplicação
26
+ COPY main.py .
27
+
28
+ # Expor a porta que o FastAPI usará
29
+ EXPOSE 8000
30
+
31
+ # Comando para rodar a aplicação
32
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Dockerfile.hf ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Usar uma imagem base leve de Python
2
+ FROM python:3.11-slim
3
+
4
+ # Evitar a geração de arquivos .pyc e habilitar o log em tempo real
5
+ ENV PYTHONDONTWRITEBYTECODE 1
6
+ ENV PYTHONUNBUFFERED 1
7
+
8
+ # Criar um usuário não-root para o Hugging Face Spaces
9
+ RUN useradd -m -u 1000 user
10
+ USER user
11
+ ENV HOME=/home/user \
12
+ PATH=/home/user/.local/bin:$PATH
13
+
14
+ WORKDIR $HOME/app
15
+
16
+ # Instalar dependências do sistema como root
17
+ USER root
18
+ RUN apt-get update && apt-get install -y --no-install-recommends \
19
+ texlive-latex-base \
20
+ texlive-fonts-recommended \
21
+ texlive-latex-extra \
22
+ && apt-get clean \
23
+ && rm -rf /var/lib/apt/lists/*
24
+
25
+ # Voltar para o usuário não-root
26
+ USER user
27
+
28
+ # Instalar dependências Python
29
+ COPY --chown=user requirements.txt .
30
+ RUN pip install --no-cache-dir --user -r requirements.txt
31
+
32
+ # Copiar o código da aplicação
33
+ COPY --chown=user main.py .
34
+
35
+ # O Hugging Face Spaces usa a porta 7860 por padrão
36
+ EXPOSE 7860
37
+
38
+ # Comando para rodar a aplicação na porta correta
39
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LaTeX to PDF API (FastAPI + Docker)
2
+
3
+ Esta é uma API simples construída com FastAPI que recebe conteúdo LaTeX via POST e retorna um arquivo PDF compilado.
4
+
5
+ ## Como rodar com Docker
6
+
7
+ 1. Certifique-se de ter o Docker instalado.
8
+ 2. No diretório do projeto, construa a imagem:
9
+ ```bash
10
+ docker build -t latex-api .
11
+ ```
12
+ 3. Inicie o container:
13
+ ```bash
14
+ docker run -p 8000:8000 latex-api
15
+ ```
16
+
17
+ ## Como usar a API
18
+
19
+ ### Endpoint: `POST /compile`
20
+
21
+ Envia o conteúdo LaTeX para compilação.
22
+
23
+ **Corpo da Requisição (JSON):**
24
+ ```json
25
+ {
26
+ "content": "\\documentclass{article}\\begin{document}Olá, este é um teste do LaTeX!\\end{document}"
27
+ }
28
+ ```
29
+
30
+ **Resposta:**
31
+ Um arquivo binário PDF (`application/pdf`).
32
+
33
+ ### Exemplo com `curl`:
34
+
35
+ ```bash
36
+ curl -X POST "http://localhost:8000/compile" \
37
+ -H "Content-Type: application/json" \
38
+ -d '{"content": "\\documentclass{article}\\begin{document}Hello World!\\end{document}"}' \
39
+ --output document.pdf
40
+ ```
41
+
42
+ ## Estrutura do Projeto
43
+
44
+ - `main.py`: Código da API FastAPI.
45
+ - `Dockerfile`: Configuração para criar a imagem Docker com Python e TeX Live.
46
+ - `requirements.txt`: Dependências Python.
main.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import uuid
4
+ import shutil
5
+ from fastapi import FastAPI, HTTPException, BackgroundTasks
6
+ from fastapi.responses import FileResponse
7
+ from pydantic import BaseModel
8
+
9
+ app = FastAPI(title="LaTeX to PDF API")
10
+
11
+ # Diretório temporário para processamento
12
+ TEMP_DIR = "/tmp/latex_processing"
13
+ os.makedirs(TEMP_DIR, exist_ok=True)
14
+
15
+ class LatexRequest(BaseModel):
16
+ content: str
17
+
18
+ def cleanup(directory: str):
19
+ """Remove o diretório temporário após o uso."""
20
+ if os.path.exists(directory):
21
+ shutil.rmtree(directory)
22
+
23
+ @app.post("/compile")
24
+ async def compile_latex(request: LatexRequest, background_tasks: BackgroundTasks):
25
+ job_id = str(uuid.uuid4())
26
+ job_dir = os.path.join(TEMP_DIR, job_id)
27
+ os.makedirs(job_dir, exist_ok=True)
28
+
29
+ tex_file = os.path.join(job_dir, "document.tex")
30
+ pdf_file = os.path.join(job_dir, "document.pdf")
31
+
32
+ # Salva o conteúdo LaTeX no arquivo
33
+ with open(tex_file, "w") as f:
34
+ f.write(request.content)
35
+
36
+ try:
37
+ # Executa o pdflatex
38
+ # -interaction=nonstopmode evita que o processo pare em erros
39
+ process = subprocess.run(
40
+ ["pdflatex", "-interaction=nonstopmode", "-output-directory", job_dir, tex_file],
41
+ stdout=subprocess.PIPE,
42
+ stderr=subprocess.PIPE,
43
+ text=True
44
+ )
45
+
46
+ if not os.path.exists(pdf_file):
47
+ # Se o PDF não foi gerado, houve um erro no LaTeX
48
+ error_msg = process.stdout if process.stdout else process.stderr
49
+ # cleanup(job_dir) # Removido para evitar conflito com FileResponse imediato
50
+ raise HTTPException(status_code=400, detail=f"Erro na compilação LaTeX: {error_msg}")
51
+
52
+ # Retorna o arquivo e agenda a limpeza
53
+ response = FileResponse(pdf_file, media_type="application/pdf", filename="document.pdf")
54
+ background_tasks.add_task(cleanup, job_dir)
55
+ return response
56
+
57
+ except Exception as e:
58
+ cleanup(job_dir)
59
+ if isinstance(e, HTTPException):
60
+ raise e
61
+ raise HTTPException(status_code=500, detail=str(e))
62
+
63
+ @app.get("/health")
64
+ async def health_check():
65
+ return {"status": "healthy"}
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pydantic
4
+ python-multipart
test.pdf ADDED
Binary file (14 kB). View file