# 🗜️ PDF Compression в n8n ## 📋 Проблема Пользователь загружает PDF 5-10 MB → долгая обработка OCR ## ✅ Решение: 2-уровневая система --- ## 🎯 Уровень 1: Frontend (React) **Что делаем:** - JPG/PNG → сжатие до 2MB → конвертация в PDF - PDF < 5MB → пропускаем - PDF > 10MB → **отклоняем** с сообщением **Код:** `frontend/src/utils/pdfConverter.ts` ✅ УЖЕ ГОТОВО --- ## 🎯 Уровень 2: Backend (n8n) ### Workflow для сжатия PDF > 5MB ``` Webhook (file upload) ↓ IF Node: file_size > 5 MB? ├─ FALSE → S3 Upload (оригинал) └─ TRUE → Python Code Node (compress) ↓ S3 Upload (compressed) ``` --- ## 🐍 Python Code Node - PDF Compression ### Установка библиотеки в n8n ```bash # В контейнере n8n docker exec -it sh apk add --no-cache python3 py3-pip pip3 install pypdf ``` ### Code Node конфигурация **Language:** Python **Mode:** Run Once for All Items **Code:** ```python import io from pypdf import PdfReader, PdfWriter # Получаем binary data из предыдущей ноды input_data = items[0].binary['data'] pdf_bytes = input_data # Читаем PDF reader = PdfReader(io.BytesIO(pdf_bytes)) writer = PdfWriter() # Копируем страницы с оптимизацией for page in reader.pages: # Удаляем неиспользуемые объекты page.compress_content_streams() writer.add_page(page) # Применяем сжатие writer.compress_identical_objects() writer.remove_duplication() # Сжимаем изображения (если есть) for page in writer.pages: for img in page.images: img.replace(img.image, quality=70) # Выводим в bytes output = io.BytesIO() writer.write(output) compressed_bytes = output.getvalue() # Логируем результат original_size = len(pdf_bytes) / (1024 * 1024) compressed_size = len(compressed_bytes) / (1024 * 1024) compression_ratio = ((original_size - compressed_size) / original_size) * 100 print(f"✅ Compressed: {original_size:.2f}MB → {compressed_size:.2f}MB ({compression_ratio:.1f}% reduction)") # Возвращаем binary data return { 'binary': { 'data': compressed_bytes }, 'json': { 'original_size_mb': round(original_size, 2), 'compressed_size_mb': round(compressed_size, 2), 'compression_ratio': round(compression_ratio, 1), 'success': True } } ``` --- ## 🔧 Вариант 2: Execute Command (Ghostscript) **Требует:** `ghostscript` установлен в системе ### Execute Command Node: ```bash #!/bin/bash INPUT="/tmp/input_{{ $json.file_id }}.pdf" OUTPUT="/tmp/output_{{ $json.file_id }}.pdf" # Сохраняем binary в файл echo "{{ $binary.data }}" | base64 -d > "$INPUT" # Сжимаем через Ghostscript gs -sDEVICE=pdfwrite \ -dCompatibilityLevel=1.4 \ -dPDFSETTINGS=/ebook \ -dNOPAUSE \ -dQUIET \ -dBATCH \ -sOutputFile="$OUTPUT" \ "$INPUT" # Выводим compressed PDF cat "$OUTPUT" | base64 # Cleanup rm -f "$INPUT" "$OUTPUT" ``` **Параметры `-dPDFSETTINGS`:** - `/screen` - 72 DPI (минимальное качество, максимальное сжатие) - `/ebook` - 150 DPI ⭐ **рекомендуется** - `/printer` - 300 DPI - `/prepress` - 300 DPI (максимальное качество) --- ## 🔄 Полный Workflow ### 1. Webhook (File Upload) **Input:** ```json { "claim_id": "CLM-2025-10-26-ABC123", "file_type": "policy_scan", "filename": "policy.pdf", "voucher": "E1000-302372730", "session_id": "sess-xyz-456" } ``` **Binary Data:** `data` (PDF file) --- ### 2. IF Node: Check File Size **Condition:** ``` {{ $binary.data.length }} > 5242880 ``` (5MB = 5 * 1024 * 1024 bytes) --- ### 3a. FALSE → Direct Upload **S3 Upload Node** → PostgreSQL --- ### 3b. TRUE → Compress First ``` Python Code (compress) ↓ Set Binary Data ↓ S3 Upload (compressed) ↓ PostgreSQL (update file_size) ``` --- ## 📊 Результаты сжатия | Метод | Скорость | Сжатие | Качество | |-------|----------|--------|----------| | **pypdf** | Быстро | 30-50% | Хорошее ⭐ | | **Ghostscript /ebook** | Средне | 50-70% | Среднее | | **Ghostscript /screen** | Средне | 70-85% | Низкое | | **Frontend (jspdf)** | Моментально | 60-80% | Хорошее ✅ | --- ## 🎯 Итоговая стратегия ``` 📱 Пользователь загружает файл ↓ 🔍 Frontend проверка: ├─ JPG/PNG → compress + convert → PDF (✅ готово) ├─ PDF < 5MB → отправить как есть ├─ PDF 5-10MB → отправить (n8n сожмёт) └─ PDF > 10MB → ❌ отклонить 🚀 n8n workflow: ├─ file_size < 5MB → S3 + OCR └─ file_size > 5MB → Python compress → S3 + OCR ``` --- ## 🧪 Тестирование ### curl пример: ```bash # Создаём большой PDF для теста curl -o large.pdf https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf # Отправляем в n8n curl -X POST \ -F "claim_id=CLM-TEST-001" \ -F "file_type=policy_scan" \ -F "fileInput=@large.pdf" \ -F "voucher=TEST-123" \ -F "session_id=sess-test" \ https://n8n.clientright.pro/webhook/7e2abc64-eaca-4671-86e4-12786700fe95 ``` --- ## ✅ Готово! **Frontend:** ✅ Ограничение 10MB + предупреждение **n8n:** ⏳ Нужно добавить Python Code Node **Следующий шаг:** Добавить Python Code Node в workflow для файлов > 5MB