Этап 0 — Загрузка
2.3 Этап 0 — Загрузка и предобработка
Сторона клиента
Клиент отправляет сфотографированное изображение или PDF напрямую на конечную точку загрузки приложения как multipart POST. Предобработка — обязанность сервера: тонкий клиент означает, что каждая поверхность съёмки получает одну и ту же нормализацию без доставки кода обработки изображений на каждую платформу.
Сторона сервера
Маршрут загрузки проверяет запрос до какой-либо работы с хранилищем:
- Ограничение размера — размер загрузки сверяется с ограничением, определённым в продакшене.
- Проверка сигнатуры файла (magic bytes) — сервер анализирует ведущие байты буфера, чтобы подтвердить, что полезная нагрузка действительно является растровым изображением (
JPEG,PNG,WEBP,HEICи другие поддерживаемые форматы) или PDF, независимо отContent-Type, переданного клиентом. Это блокирует скрипты или разметку, протащенные под типомimage/*.
Принятые загрузки затем проходят серверную предобработку с помощью sharp:
- Ориентация — автоповорот на основе EXIF, чтобы чек был выпрямлен перед этапом чтения.
- Сжатие — изображение перекодируется в профиль размера и качества, настроенный для этапа зрения (vision).
- Хранение — обработанное изображение записывается в объектное хранилище Vercel Blob с резервным путём в базе данных на случай недоступности Blob-хранилища. Сохранённые изображения планируются к удалению согласно политике хранения.
Ответ возвращает receipt_id и ссылку на сохранённое изображение. Затем клиент вызывает POST /api/receipt/analyze для перехода на Этап 1.
Дедупликация
Точная проверка по хэшу файла выполняется до начала любой ресурсоёмкой работы: SHA-256 загруженных байтов сравнивается с ранее сохранёнными чеками. Проверка перцептивного сходства сознательно отложена до момента после извлечения содержимого, где её можно сверить с хэшем содержимого; ранний запуск визуального сравнения потратил бы эту работу на загрузки, которые точная проверка уже разрешает.
Оба случая дублирования отклоняют загрузку с ошибкой дубликата:
- Дубль того же пользователя — пользователю сообщается, что он уже загружал этот чек. Это предотвращает случайные повторные загрузки и попытки повторного получения вознаграждения.
- Межпользовательское столкновение — пользователю сообщается, что чек был загружен другим аккаунтом. Это часть защиты от фарминга.
Точные сигналы сходства настраиваются в продакшене и управляются внутренним операционным слоем.