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

257 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🗜️ 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 <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:**
```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