# 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 com redução >60%** - Compressão agressiva com qualidade ajustável (30-100%) - Redução média de 60-80% do tamanho original - Otimização de imagens e remoção de metadados - Suporte para múltiplos arquivos simultâneos - Opção de adicionar camada OCR (tornar PDF pesquisável) 2. **Divisão de PDF** - Por páginas específicas (ex: 1,3,5,7) - Por intervalos (ex: 1-5, 6 - **Download em ZIP** quando múltiplos arquivos-10) - Por chunks de tamanho fixo 3. **Mesclagem de PDFs** - Combine até 50 PDFs em um único arquivo - Preserva qualidade o - Opção de adicionar camada OCR ao PDF mescladoriginal - Ordem personalizável 4. **PDF para Imagens** - Formatos: PNG, JPG, WEBP - DPI ajustável (150-600) - **Download em ZIP** de todas as imagens - Qualidade configurável (50-100%) - Conversão de páginas específicas ou todas 5. **Imagens para PDF** - Opção de adicionar camada OCR (tornar PDF pesquisável) - 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 archiver npm install --save-dev @types/pdf-parse @types/archiver ``` Ou execute o script de instalação: ```bash npm run install-pdf-deps ``` ### 2. Instalar GraphicsMagick (Requerido para PDF → Imagens) **Docker:** O GraphicsMagick já está incluído no Dockerfile. Rebuild a imagem se necessário: ```bash docker-compose down docker-compose build --no-cache docker-compose up -d ``` **Local (desenvolvimento):** Ubuntu/Debian: ```bash sudo apt-get update sudo apt-get install graphicsmagick ``` MacOS: ```bash brew install graphicsmagick ``` Windows: - Baixe e instale: http://www.graphicsmagick.org/download.html - Adicione ao PATH do sistema Verifique a instalação: ```bash gm version ``` ### 3. Executar Migration do Banco de Dados ```bash npm run prisma:migrate ``` Ou manualmente: ```bash npx prisma migrate dev --name add_operacoes_pdf ``` ### 4. Gerar Cliente Prisma ```bash npm run prisma:generate ``` ### 5. 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} 30-100, padrão 50 para máxima compressão) - maxSizeMB: number (opcional) - enableOCR: boolean (opcional, adiciona camada OCR ao PDF - 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-da - enableOCR: boolean (opcional, adiciona camada OCR ao PDF mesclado)ta 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} - enableOCR: boolean (opcional, adiciona camada OCR ao PDF) 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) ...], "outputPaths": ["/path/compressed-1.pdf", "/path/compressed-2.pdf"], "totalOriginalSize": 1048576, "totalCompressedSize": 314572, "reduction": 70.0, "processingTime": 1234 } ``` ### Sucesso (Split/PDF para Imagens - com ZIP) ```json { "success": true, "operacaoId": "uuid", "filesCreated": 10, "outputPaths": ["/path/page-1.pdf", "/path/page-2.pdf", ...], "zipPath": "/path/arquivos-uuid.zip", "processingTime": 2345 ], "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 - **Timeout de operações:** 10 minutos (600 segundos) - Operações longas (OCR, compressão de PDFs grandes) podem levar alguns minutos - O sistema está configurado para suportar até 10 minutos de processamento ## 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: "Could not execute GraphicsMagick/ImageMagick" **Sintoma:** Erro ao converter PDF para imagens: ``` Error: Could not execute GraphicsMagick/ImageMagick: gm "convert" ... this most likely means the gm/convert binaries can't be found ``` **Causa:** GraphicsMagick não está instalado no sistema/container. **Solução:** **Docker:** ```bash # Rebuild a imagem Docker com GraphicsMagick incluído docker-compose down docker-compose build --no-cache docker-compose up -d ``` **Local:** ```bash # Ubuntu/Debian sudo apt-get install graphicsmagick # MacOS brew install graphicsmagick # Verifique a instalação gm version ``` ### Erro 504: Gateway Timeout (Timeout ao processar PDF) **Sintoma:** Operação de compressão ou OCR retorna erro 504 após ~60 segundos: ``` Failed to load resource: the server responded with a status of 504 ``` **Causa:** Operações de PDF (especialmente compressão e OCR) podem levar vários minutos para arquivos grandes. O timeout padrão de 60 segundos é insuficiente. **Solução:** As configurações de timeout foram aumentadas para **10 minutos** em: - ✅ Express server (`src/server/index.ts`) - ✅ Vite proxy (`vite.config.ts`) - ✅ Axios frontend (`PDFManipulationPage.tsx`) Se ainda ocorrer timeout: 1. Verifique se rebuild foi feito após as alterações 2. Reduza o tamanho do arquivo ou qualidade 3. Processe menos arquivos por vez 4. Para PDFs muito grandes (>50MB), considere fazer upload em partes **Dicas de performance:** - Compressão: Use qualidade 50-70 para PDFs grandes - OCR: Processe apenas páginas necessárias, não o PDF inteiro - Split: Use chunks menores para PDFs com muitas páginas ### Erro: ENOENT ao deletar arquivos do histórico **Sintoma:** Erro ao limpar histórico: ``` Error: ENOENT: no such file or directory, unlink '/path/to/file.pdf' ``` **Causa:** Tentativa de deletar arquivos que não existem mais (já foram removidos manualmente ou por outro processo). **Solução:** ✅ **Corrigido automaticamente** - O sistema agora verifica se o arquivo existe antes de tentar deletar e ignora erros ENOENT silenciosamente. ### Erro: Imagens baixadas com extensão .pdf (ou sem extensão correta) **Sintoma:** Ao baixar imagens geradas pela conversão PDF→Imagens, os arquivos vêm com extensão .pdf ou precisam ser renomeados para .png/.jpg para serem visualizados. **Causa:** O servidor não estava enviando o Content-Type correto no header HTTP, OU o frontend estava ignorando os headers do servidor e forçando o nome como `.pdf`. **Solução:** ✅ **Corrigido automaticamente** - O sistema agora: **Backend:** - Detecta automaticamente o tipo MIME correto baseado na extensão (.png, .jpg, .webp, .zip, .pdf) - Define headers HTTP apropriados (`Content-Type` e `Content-Disposition`) - Garante que o nome do arquivo no download mantém a extensão original - Adiciona logs de debug para facilitar troubleshooting **Frontend:** - Extrai o nome do arquivo do header `Content-Disposition` enviado pelo servidor - Usa o `Content-Type` correto do servidor ao criar o Blob para download - Não força mais extensão `.pdf` em todos os downloads - Adiciona log no console do browser: `Download frontend: arquivo.png (image/png)` - Libera memória do blob URL após download Se ainda ocorrer o problema: 1. Abra o Console do DevTools (F12) e verifique os logs de download 2. Verifique se os headers estão sendo recebidos corretamente na aba Network 3. Limpe o cache do browser (Ctrl+Shift+Del) 4. Teste em uma aba anônima/privada 5. Use a opção de **Download ZIP** que sempre funciona corretamente ### 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.1.2 (2026-02-27) - 🔧 **Correção DEFINITIVA de downloads** - Arquivos agora baixam com nome e extensão corretos - **Backend:** Detecta tipo MIME e define headers HTTP apropriados (Content-Type, Content-Disposition) - **Frontend:** Extrai nome do arquivo e tipo MIME dos headers da resposta - **Frontend:** Não força mais `.pdf` em todos os downloads - usa nome real do servidor - **Frontend:** Cria Blob com Content-Type correto preservando o formato original - Adiciona logs de debug no backend e frontend para troubleshooting - Suporta formato 'jpeg' além de 'jpg' - Fallback para PNG em formatos não suportados - Libera memória de blob URLs após download - 🐛 **Melhorias no pdfToImages** - Adicionado suporte para 'jpeg' e fallback para formatos inválidos ### v1.1.1 (2026-02-27) - 🔧 **Correção de timeout 504** - Aumentado timeout para 10 minutos em todas as camadas - Express server: 600 segundos - Vite proxy: 600 segundos - Axios frontend: 600 segundos - 🗑️ **Correção ENOENT** - Sistema agora ignora arquivos já deletados ao limpar histórico - 📋 **Gerenciamento de histórico** - Botões para limpar histórico completo ou arquivos antigos - 🐛 **Melhorias de estabilidade** - Verificação de existência de arquivos antes de deletar - 📚 **Documentação expandida** - Adicionado troubleshooting completo ### v1.1.0 (2026-02-27) - 🚀 **Compressão agressiva** com redução >60% do tamanho original - 📦 **Download em ZIP** para operações com múltiplos arquivos (split, pdfToImages) - 🔍 **OCR embutido** - opção de tornar PDFs pesquisáveis (compress, merge, imagesToPDF) - ⚡ **Otimização de imagens** com qualidade ajustável (30-100%) - 🎯 **Interface aprimorada** com indicadores visuais e opções de OCR ### 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