pdf: add new feature
Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
1 parent
a63aaeb655
commit
61a1631519
14 files changed
+3091
-1
No files matched your search
@@ -0,0 +1,421 @@
|
||||
# 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
|
||||
Reference in new issue
Block a user