Files
aiform_dev/N8N_PDF_COMPRESS.md
AI Assistant 647abf6578 feat: Интеграция n8n + Redis Pub/Sub + SSE для real-time обработки заявок
🎯 Основные изменения:

Backend:
-  Добавлен SSE endpoint для real-time событий (/api/v1/events/{task_id})
-  Redis Pub/Sub для публикации/подписки на события OCR/Vision
-  Удален aioboto3 из requirements.txt (конфликт зависимостей)
-  Добавлен OCR worker (deprecated, логика перенесена в n8n)

Frontend (React):
-  Автогенерация claim_id и session_id
-  Клиентская конвертация файлов в PDF (JPG/PNG/HEIC/WEBP)
-  Сжатие изображений до 2MB перед конвертацией
-  SSE подписка на события OCR/Vision в Step1Policy
-  Валидация документов (полис vs неподходящий контент)
-  Real-time прогресс загрузки и обработки файлов
-  Интеграция с n8n webhooks для проверки полиса и загрузки файлов

n8n Workflows:
-  Проверка полиса в MySQL + запись в PostgreSQL
-  Загрузка файлов в S3 + OCR + Vision AI
-  Публикация событий в Redis через backend API
-  Валидация документов (распознавание полисов ERV)

Документация:
- 📝 N8N_INTEGRATION.md - интеграция с n8n
- 📝 N8N_SQL_QUERIES.md - SQL запросы для workflows
- 📝 N8N_PDF_COMPRESS.md - сжатие PDF
- 📝 N8N_STIRLING_COMPRESS.md - интеграция Stirling-PDF

Утилиты:
- 🔧 monitor_redis.py/sh - мониторинг Redis Pub/Sub
- 🔧 test_redis_events.sh - тестирование событий
- 🔧 pdfConverter.ts - клиентская конвертация в PDF

Архитектура:
React → n8n webhooks (sync) → MySQL/PostgreSQL/S3
      → n8n workflows (async) → OCR/Vision → Redis Pub/Sub → SSE → React
2025-10-27 08:33:16 +03:00

5.8 KiB
Raw Permalink Blame History

🗜️ 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

# В контейнере n8n
docker exec -it <n8n_container_name> sh
apk add --no-cache python3 py3-pip
pip3 install pypdf

Code Node конфигурация

Language: Python
Mode: Run Once for All Items

Code:

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:

#!/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:

{
  "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 пример:

# Создаём большой 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