CM Consultor e97adca143 fix: compressão real p/ stream DCTDecode + auth c/ chave vazia
- Substitui xobj._data por page.images[].replace() em compress.py e pdfa.py
- Adiciona compress_with_stats() com feedback honesto na UI
- Trata PDFTOOLKIT_API_KEY vazia como modo dev (auth desabilitado)
- Atualiza engine.py e app.py para exibir redução real ou 'já otimizado'
2026-08-09 05:01:16 +00:00

pdf-toolkit

Transforme, otimize e gerencie arquivos PDF com facilidade.

  • Interface Web: Streamlit com upload drag-and-drop e configuração visual
  • API REST: FastAPI com documentação OpenAPI automática em /docs
  • Autenticação: API Key via header X-API-Key (configurável via env var)
  • Docker: containers prontos para produção via docker-compose
  • Operações: compressão, PDF/A ↔ PDF comum, merge, split, rotação, extração de texto e imagens

🚀 Começando

Pré-requisitos

  • Python 3.12+
  • pip
  • Docker (opcional, para containers)

Instalação (sem Docker)

git clone <url-do-repositorio> pdf-toolkit
cd pdf-toolkit
pip install -r requirements.txt

Execução (sem Docker)

Streamlit (interface web):

streamlit run app.py --server.port 8550

API REST:

uvicorn api:app --host 0.0.0.0 --port 8555 --reload

Acesse:


📋 Operações disponíveis

Operação CLI API Streamlit
Comprimir PDF ✅ POST /compress ✅
PDF/A → PDF comum ✅ POST /pdfa-to-regular ✅
Comprimir mantendo PDF/A ✅ POST /compress-pdfa ✅
Merge (juntar PDFs) ✅ POST /merge ✅
Split (extrair páginas) ✅ POST /split ✅
Extrair páginas específicas ✅ POST /extract-pages ✅
Rotacionar páginas ✅ POST /rotate ✅
Extrair texto ✅ POST /extract-text ✅
Extrair imagens ✅ POST /extract-images ✅
Inspecionar metadados ✅ POST /inspect ✅

Níveis de compressão

Preset Qualidade Dimensão máx Descrição
screen 30 1200px Agressivo — mínimo tamanho
ebook 60 2000px Equilibrado — padrão
printer 85 3500px Leve — alta qualidade
prepress 95 5000px Mínima perda

🧠 Arquitetura

pdf-toolkit/
├── app.py               # Interface Streamlit (GUI)
├── api.py               # API REST (FastAPI)
├── config.py            # Constantes e limites
├── requirements.txt     # Dependências
├── core/
│   ├── engine.py        # Orquestrador central
│   ├── compress.py      # Compressão e re-amostragem
│   ├── operations.py    # Merge, split, rotate, extract
│   ├── validators.py    # Validação de PDFs
│   └── pdfa.py          # Detecção e conversão PDF/A
├── scripts/
│   ├── run-web.sh       # Inicia Streamlit
│   └── run-api.sh       # Inicia API
├── tests/               # Testes unitários
├── docs/
│   ├── ARCHITECTURE.md  # Detalhamento técnico
│   └── API.md           # Documentação da API
└── tmp/                 # Arquivos temporários (gitignored)

Decisões técnicas

  • pypdf: manipulação PDF 100% Python, sem dependências binárias
  • Pillow: re-amostragem de imagens com redimensionamento proporcional
  • FastAPI: tipagem automática, validação de entrada, OpenAPI nativo
  • Streamlit: prototipação rápida de GUI sem HTML/JS
  • Sem Ghostscript: mantido leve — pypdf + Pillow cobre ~90% dos casos

Limitações conhecidas

  • A compressão re-amostra imagens embutidas; PDFs sem imagens reduzem pouco
  • A detecção de PDF/A é heurística (via metadados XMP + OutputIntents)
  • Preview visual de páginas requer poppler-utils + pdf2image (não incluso)
  • PDFs criptografados com senha não são suportados

🔐 Autenticação da API

A API suporta autenticação via API Key no header X-API-Key.

Configuração

Defina a variável de ambiente PDFTOOLKIT_API_KEY:

export PDFTOOLKIT_API_KEY="sua-chave-secreta-aqui"

Se a variável não estiver definida, a API roda sem autenticação (modo desenvolvimento).

Uso com curl

curl -X POST http://localhost:8555/compress \
  -H "X-API-Key: sua-chave-secreta-aqui" \
  -F "file=@documento.pdf" \
  -o comprimido.pdf

Endpoints públicos (sem auth)

  • GET / — raiz informativa
  • GET /health — health check

🐳 Docker

docker-compose (desenvolvimento local)

cp .env.example .env      # configure sua API Key
sed -i 's/PDFTOOLKIT_API_KEY=.*/PDFTOOLKIT_API_KEY=minha-chave/' .env

docker compose up -d --build

# Acesse:
# - Streamlit: http://localhost:8550
# - API:       http://localhost:8555
# - Swagger:   http://localhost:8555/docs

Build individual para Swarm / registry

Cada serviço tem seu próprio Dockerfile independente:

# API
docker build -t gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-api:1.0.0 -f Dockerfile.api .
docker push gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-api:1.0.0

# Web
docker build -t gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-web:1.0.0 -f Dockerfile.web .
docker push gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-web:1.0.0

Deploy no Docker Swarm

# pdf-toolkit-stack.yml
docker stack deploy -c docker-compose.yml pdf-toolkit

Ou use imagens previamente buildadas (recomendado para Swarm):

# Ajuste o docker-compose.yml para usar as imagens do registry
docker stack deploy -c docker-compose.yml pdf-toolkit

Estrutura dos containers

Cada container é uma imagem independente otimizada para deploy individual:

  • pdf-toolkit-api: FastAPI + uvicorn, porta 8555
  • pdf-toolkit-web: Streamlit, porta 8550, depende do serviço api
  • Volume compartilhado uploads para arquivos temporários
  • Healthcheck embutido em ambos os containers

🧪 Testes

python -m pytest tests/ -v

📦 Licença

MIT

Description
Ferramenta de transformação e otimização de PDFs — compressão, PDF/A, merge, split, rotação e extração. GUI Streamlit + API FastAPI.
Readme 115 KiB
Languages
Python 99.2%
Shell 0.8%