Files
aiform_dev/N8N_PDF_COMPRESS.md

257 lines
5.8 KiB
Markdown
Raw Permalink Normal View History

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