- Исправлена ошибка ReferenceError при загрузке черновиков - Переименована локальная переменная claimId в finalClaimId для избежания конфликта с параметром функции - Обновлена логика извлечения claim_id из разных источников (claim.claim_id, payload.claim_id, body.claim_id, claim.id) - Добавлен fallback на параметр claimId функции для надёжности
5.8 KiB
5.8 KiB
🗜️ 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