Files
pdf-toolkit/docs/ARCHITECTURE.md
CM Consultor 84d4a1eab5 feat: initial release — pdf-toolkit v1.0.0
Core operations:
- Compress PDF (3 presets: screen, ebook, printer, prepress)
- PDF/A detection and conversion to regular PDF
- Compress while preserving PDF/A structure
- Merge multiple PDFs
- Split/extract pages by range
- Rotate pages
- Extract text and images

Interface:
- Streamlit web GUI (app.py)
- FastAPI REST API with auto OpenAPI docs (api.py)

Docs:
- README.md, ARCHITECTURE.md, API.md
- Unit tests (15/15 passing)
2026-08-09 02:15:22 +00:00

5.2 KiB

Arquitetura do pdf-toolkit

Visão geral

O pdf-toolkit é um sistema de duas faces: GUI (Streamlit) e API REST (FastAPI), ambas compartilhando o mesmo núcleo (core/) e configurações (config.py).

┌─────────────────────┐     ┌──────────────────────┐
│  Streamlit (app.py) │     │  FastAPI (api.py)    │
│  ─ Porta 8550       │     │  ─ Porta 8555        │
│  ─ Upload drag-drop │     │  ─ Swagger /docs     │
│  ─ Preview visual   │     │  ─ Redoc /redoc      │
└────────┬────────────┘     └──────────┬───────────┘
         │                             │
         └──────────┬──────────────────┘
                    │
         ┌──────────▼───────────┐
         │    core/ (engine)    │
         │  ┌─────────────────┐ │
         │  │   engine.py     │ │← Orquestrador (facade)
         │  │   validators.py │ │← Valida entradas
         │  │   compress.py   │ │← Compressão/redução
         │  │   pdfa.py       │ │← PDF/A detection & strip
         │  │   operations.py │ │← Merge, split, rotate...
         │  └─────────────────┘ │
         └──────────────────────┘

Fluxo de dados

  1. Entrada: bytes do PDF via upload (Streamlit) ou HTTP multipart (API)
  2. Validação: validators.validate_pdf() checa magic number, lê metadados
  3. Detecção PDF/A: pdfa.detect_pdfa() verifica XMP metadata e OutputIntents
  4. Transformação: operação específica (compressão, split, etc.)
  5. Saída: bytes transformados → download (Streamlit) ou Response (API)

Módulo core/engine.py

PDFEngine é uma classe de fachada que unifica todos os submódulos. Cada método:

  • Recebe bytes (ou lista de bytes)
  • Retorna bytes (ou metadados dict)
  • Propaga exceções para o caller (Streamlit ou FastAPI)
engine = PDFEngine()
info = engine.inspect(data, "doc.pdf")
comprimido = engine.compress(data, preset="ebook")

Módulo core/compress.py

Estratégia de compressão

  1. Para cada página, varre /Resources/XObject em busca de /Subtype == /Image
  2. Extrai dados brutos da imagem
  3. Redimensiona proporcionalmente se exceder max_dim (LANCZOS)
  4. Re-comprime em JPEG com quality definida
  5. Substitui _data do objeto XObject
  6. Re-escreve o PDF com PdfWriter.write_stream() (já faz compressão de streams)

Por que não usamos linearização?

pypdf não suporta linearização true (fast web view). A opção linearize_pdf() apenas re-escreve o PDF, o que já melhora a estrutura. Para linearização real, seria necessário Ghostscript ou qpdf.


Módulo core/pdfa.py

Detecção de PDF/A

Dois métodos complementares:

  1. Metadados XMP: busca padrão pdfaid:part + pdfaid:conformance via regex
  2. OutputIntents: verifica /OutputIntents no dicionário raiz do PDF (obrigatório em PDF/A)

Conversão PDF/A → PDF comum

  • Remove metadados XMP que declaram PDF/A
  • Remove dicionário /OutputIntents
  • Preserva conteúdo visual integralmente
  • Mantém metadados não-PDF/A (autor, título, etc.)

Módulo core/operations.py

Operações independentes que não dependem entre si:

Função Descrição
merge_pdfs() Concatena PDFs em ordem
split_pdf() Extrai intervalos → múltiplos PDFs
extract_pages() Extrai páginas específicas → 1 PDF
rotate_pages() Rotaciona páginas (90/180/270)
extract_text() Extrai texto de todas as páginas
extract_images() Extrai imagens embutidas

API (FastAPI)

A API usa File (multipart) para upload e Response para download.

Validação automática via FastAPI:

  • Tipo dos parâmetros
  • Limite de tamanho (_read_file())
  • Presets válidos

Documentação: /docs (Swagger) e /redoc (Redoc) são gerados automaticamente.


Streamlit (GUI)

A GUI organiza-se em:

  1. Sidebar: upload + seleção de operação + parâmetros + botão executar
  2. Área principal: preview dos arquivos ou resultados

Estados:

  • Antes de executar: exibe metadados dos PDFs carregados
  • Executando: barra de progresso com descrição
  • Resultado: download individual ou ZIP com múltiplos arquivos

Dependências

Pacote Uso
streamlit Interface web
fastapi + uvicorn API REST
pypdf Leitura/escrita de PDF
Pillow Processamento de imagens
python-multipart Upload na API

Próximas melhorias possíveis

  • Integração com Ghostscript para compressão mais agressiva
  • Preview visual de páginas via pdf2image + poppler-utils
  • Suporte a PDFs criptografados (senha)
  • OCR em PDFs scaneados (Tesseract)
  • Concorrência em lote com asyncio/ThreadPoolExecutor
  • Autenticação na API (API keys)
  • Dockerfile para deploy