422 lines
8.8 KiB
Markdown
422 lines
8.8 KiB
Markdown
# Funcionalidade de Manipulação de PDFs
|
|
|
|
## Visão Geral
|
|
|
|
Sistema completo de manipulação de arquivos PDF com as seguintes funcionalidades:
|
|
|
|
### Recursos Implementados
|
|
|
|
1. **Compressão de PDF sem perda de qualidade**
|
|
- Compressão inteligente mantendo qualidade entre 50-100%
|
|
- Remoção de metadados desnecessários
|
|
- Otimização de streams de objetos
|
|
- Suporte para múltiplos arquivos simultâneos
|
|
|
|
2. **Divisão de PDF**
|
|
- Por páginas específicas (ex: 1,3,5,7)
|
|
- Por intervalos (ex: 1-5, 6-10)
|
|
- Por chunks de tamanho fixo
|
|
|
|
3. **Mesclagem de PDFs**
|
|
- Combine até 50 PDFs em um único arquivo
|
|
- Preserva qualidade original
|
|
- Ordem personalizável
|
|
|
|
4. **PDF para Imagens**
|
|
- Formatos: PNG, JPG, WEBP
|
|
- DPI ajustável (150-600)
|
|
- Qualidade configurável (50-100%)
|
|
- Conversão de páginas específicas ou todas
|
|
|
|
5. **Imagens para PDF**
|
|
- Suporta múltiplas imagens (até 100)
|
|
- Ajuste automático ao tamanho da página
|
|
- Suporta PNG, JPG, JPEG, WEBP
|
|
|
|
6. **OCR (Reconhecimento Ótico de Caracteres)**
|
|
- Extração de texto de PDFs escaneados
|
|
- Suporte para Português, Inglês e Espanhol
|
|
- Retorna confiança da extração
|
|
- Processamento por página
|
|
|
|
7. **Informações do PDF**
|
|
- Número de páginas
|
|
- Tamanho do arquivo
|
|
- Metadados (título, autor, criador, etc.)
|
|
- Datas de criação e modificação
|
|
|
|
## Instalação
|
|
|
|
### 1. Instalar Dependências
|
|
|
|
```bash
|
|
npm install pdf-lib pdf-parse pdf2pic tesseract.js
|
|
npm install --save-dev @types/pdf-parse
|
|
```
|
|
|
|
Ou execute o script de instalação:
|
|
|
|
```bash
|
|
npm run install-pdf-deps
|
|
```
|
|
|
|
### 2. Executar Migration do Banco de Dados
|
|
|
|
```bash
|
|
npm run prisma:migrate
|
|
```
|
|
|
|
Ou manualmente:
|
|
|
|
```bash
|
|
npx prisma migrate dev --name add_operacoes_pdf
|
|
```
|
|
|
|
### 3. Gerar Cliente Prisma
|
|
|
|
```bash
|
|
npm run prisma:generate
|
|
```
|
|
|
|
### 4. Criar Diretórios Necessários
|
|
|
|
Os diretórios serão criados automaticamente na primeira execução, mas você pode criá-los manualmente:
|
|
|
|
```bash
|
|
mkdir -p storage/temp/pdf-ops
|
|
mkdir -p storage/pdf-output
|
|
mkdir -p storage/temp/uploads
|
|
```
|
|
|
|
## Uso
|
|
|
|
### Frontend
|
|
|
|
Acesse a página de manipulação de PDFs através da rota:
|
|
|
|
```
|
|
/pdf
|
|
```
|
|
|
|
### API Endpoints
|
|
|
|
Todas as rotas requerem autenticação via Bearer token.
|
|
|
|
#### 1. Comprimir PDF
|
|
|
|
```http
|
|
POST /api/pdf/compress
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File[] (array de PDFs)
|
|
- quality: number (50-100, padrão 95)
|
|
- maxSizeMB: number (opcional)
|
|
```
|
|
|
|
#### 2. Dividir PDF
|
|
|
|
```http
|
|
POST /api/pdf/split
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File (único PDF)
|
|
- splitType: 'pages' | 'range' | 'chunks'
|
|
- pages: string (ex: "1,2,3") - para splitType='pages'
|
|
- ranges: string (ex: "1-5,6-10") - para splitType='range'
|
|
- chunkSize: number - para splitType='chunks'
|
|
```
|
|
|
|
#### 3. Mesclar PDFs
|
|
|
|
```http
|
|
POST /api/pdf/merge
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File[] (mínimo 2 PDFs)
|
|
```
|
|
|
|
#### 4. PDF para Imagens
|
|
|
|
```http
|
|
POST /api/pdf/pdf-to-images
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File (único PDF)
|
|
- format: 'png' | 'jpg' | 'webp' (padrão: png)
|
|
- quality: number (50-100, padrão: 95)
|
|
- density: number (DPI, 150-600, padrão: 300)
|
|
- pages: string (opcional, ex: "[1,2,3]" ou "all")
|
|
```
|
|
|
|
#### 5. Imagens para PDF
|
|
|
|
```http
|
|
POST /api/pdf/images-to-pdf
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File[] (array de imagens)
|
|
- fitToPage: boolean (padrão: true)
|
|
- pageSize: string (opcional, JSON: {"width":595,"height":842})
|
|
```
|
|
|
|
#### 6. OCR
|
|
|
|
```http
|
|
POST /api/pdf/ocr
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File (único PDF)
|
|
- language: string ('por' | 'eng' | 'spa', padrão: 'por')
|
|
- pages: string (opcional, ex: "[1,2]" ou "all")
|
|
```
|
|
|
|
#### 7. Informações do PDF
|
|
|
|
```http
|
|
POST /api/pdf/info
|
|
Content-Type: multipart/form-data
|
|
Authorization: Bearer {token}
|
|
|
|
Body:
|
|
- files: File (único PDF)
|
|
```
|
|
|
|
#### 8. Histórico de Operações
|
|
|
|
```http
|
|
GET /api/pdf/history?page=1&limit=20
|
|
Authorization: Bearer {token}
|
|
```
|
|
|
|
#### 9. Download de Arquivo Processado
|
|
|
|
```http
|
|
GET /api/pdf/download/:operacaoId/:fileIndex
|
|
Authorization: Bearer {token}
|
|
```
|
|
|
|
## Estrutura de Resposta
|
|
|
|
### Sucesso (Compressão)
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"operacaoId": "uuid",
|
|
"results": [
|
|
{
|
|
"originalName": "documento.pdf",
|
|
"originalSize": 1048576,
|
|
"compressedSize": 524288,
|
|
"reduction": 50.0,
|
|
"outputPath": "/path/to/compressed.pdf"
|
|
}
|
|
],
|
|
"totalOriginalSize": 1048576,
|
|
"totalCompressedSize": 524288,
|
|
"totalReduction": 50.0,
|
|
"processingTime": 1234
|
|
}
|
|
```
|
|
|
|
### Sucesso (OCR)
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"operacaoId": "uuid",
|
|
"result": {
|
|
"text": "Texto extraído completo...",
|
|
"confidence": 95.5,
|
|
"pages": [
|
|
{
|
|
"pageNumber": 1,
|
|
"text": "Texto da página 1...",
|
|
"confidence": 96.2
|
|
}
|
|
]
|
|
},
|
|
"processingTime": 5678
|
|
}
|
|
```
|
|
|
|
### Erro
|
|
|
|
```json
|
|
{
|
|
"error": "Falha ao processar arquivo",
|
|
"message": "Detalhes específicos do erro"
|
|
}
|
|
```
|
|
|
|
## Modelo de Dados
|
|
|
|
### OperacaoPDF
|
|
|
|
```typescript
|
|
interface OperacaoPDF {
|
|
id: string;
|
|
tipoOperacao: 'COMPRIMIR' | 'DIVIDIR' | 'MESCLAR' | 'PDF_PARA_IMAGEM' | 'IMAGEM_PARA_PDF' | 'OCR';
|
|
status: 'PROCESSANDO' | 'CONCLUIDO' | 'ERRO';
|
|
usuarioId: string;
|
|
arquivosOriginais: string[];
|
|
arquivosResultado: string[];
|
|
tamanhoOriginal: bigint;
|
|
tamanhoResultado: bigint | null;
|
|
parametros: any;
|
|
mensagemErro: string | null;
|
|
detalhesOCR: any | null;
|
|
tempoProcessamento: number | null;
|
|
criadoEm: Date;
|
|
atualizadoEm: Date;
|
|
}
|
|
```
|
|
|
|
## Segurança
|
|
|
|
- ✅ Autenticação obrigatória em todas as rotas
|
|
- ✅ Validação de tipos de arquivo (apenas PDF e imagens)
|
|
- ✅ Limite de tamanho de arquivo (100MB por arquivo)
|
|
- ✅ Limite de quantidade de arquivos por operação
|
|
- ✅ Sanitização de nomes de arquivo
|
|
- ✅ Isolamento de arquivos por operação
|
|
- ✅ Limpeza automática de arquivos temporários
|
|
|
|
## Performance
|
|
|
|
- ✅ Processamento assíncrono
|
|
- ✅ Otimização de memória com streams
|
|
- ✅ Compressão sem perda de qualidade perceptível
|
|
- ✅ Cache de workers de OCR
|
|
- ✅ Índices no banco de dados para consultas rápidas
|
|
- ✅ Limpeza automática de arquivos antigos
|
|
|
|
## Tratamento de Erros
|
|
|
|
Todos os erros são:
|
|
- Logados no console do servidor
|
|
- Registrados no banco de dados (tabela operacoes_pdf)
|
|
- Retornados ao cliente com mensagens descritivas
|
|
- Capturados por try-catch em todas as operações
|
|
|
|
## Limitações
|
|
|
|
- Tamanho máximo por arquivo: 100MB
|
|
- Máximo de arquivos para compressão: 10
|
|
- Máximo de arquivos para mesclagem: 50
|
|
- Máximo de imagens para conversão em PDF: 100
|
|
- Arquivos processados são mantidos por 24 horas
|
|
|
|
## Manutenção
|
|
|
|
### Limpeza de Arquivos Antigos
|
|
|
|
Execute periodicamente (recomendado: diariamente via cron):
|
|
|
|
```typescript
|
|
import { PDFService } from './src/services/pdfService';
|
|
|
|
// Remove arquivos com mais de 24 horas
|
|
await PDFService.cleanupOldFiles(24);
|
|
```
|
|
|
|
### Monitoramento
|
|
|
|
Consulte a tabela `operacoes_pdf` para:
|
|
- Estatísticas de uso
|
|
- Taxa de erro
|
|
- Tempo médio de processamento
|
|
- Operações mais utilizadas
|
|
|
|
```sql
|
|
-- Operações por tipo
|
|
SELECT "tipoOperacao", COUNT(*) as total
|
|
FROM operacoes_pdf
|
|
GROUP BY "tipoOperacao"
|
|
ORDER BY total DESC;
|
|
|
|
-- Taxa de sucesso
|
|
SELECT
|
|
status,
|
|
COUNT(*) as total,
|
|
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 2) as percentual
|
|
FROM operacoes_pdf
|
|
GROUP BY status;
|
|
|
|
-- Tempo médio por operação
|
|
SELECT
|
|
"tipoOperacao",
|
|
AVG("tempoProcessamento") as tempo_medio_ms,
|
|
MIN("tempoProcessamento") as tempo_min_ms,
|
|
MAX("tempoProcessamento") as tempo_max_ms
|
|
FROM operacoes_pdf
|
|
WHERE status = 'CONCLUIDO'
|
|
GROUP BY "tipoOperacao";
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Erro: "Tesseract worker failed"
|
|
|
|
Solução: Certifique-se de que o Tesseract está instalado corretamente:
|
|
|
|
```bash
|
|
npm install tesseract.js --force
|
|
```
|
|
|
|
### Erro: "Cannot find module 'sharp'"
|
|
|
|
Solução: Reinstale o Sharp com rebuild:
|
|
|
|
```bash
|
|
npm uninstall sharp
|
|
npm install sharp
|
|
npm rebuild sharp
|
|
```
|
|
|
|
### Erro: "ENOSPC: no space left on device"
|
|
|
|
Solução: Aumente o espaço em disco ou execute a limpeza:
|
|
|
|
```bash
|
|
npm run cleanup-pdf-files
|
|
```
|
|
|
|
### Performance lenta no OCR
|
|
|
|
Solução: Reduza o DPI ou processe menos páginas por vez.
|
|
|
|
## Suporte
|
|
|
|
Para questões ou problemas:
|
|
1. Verifique os logs do servidor
|
|
2. Consulte a tabela `operacoes_pdf` para detalhes do erro
|
|
3. Verifique se os diretórios de storage têm permissões corretas
|
|
4. Certifique-se de que todas as dependências estão instaladas
|
|
|
|
## Changelog
|
|
|
|
### v1.0.0 (2026-02-27)
|
|
- ✅ Implementação inicial
|
|
- ✅ Compressão sem perda de qualidade
|
|
- ✅ Divisão de PDFs
|
|
- ✅ Mesclagem de PDFs
|
|
- ✅ Conversão PDF para imagens
|
|
- ✅ Conversão de imagens para PDF
|
|
- ✅ OCR com Tesseract
|
|
- ✅ Histórico de operações
|
|
- ✅ Interface React completa
|
|
- ✅ Validação e segurança
|