Публикация постов: где ломается загрузка изображений
Типичная публикация постов устроена так: пользователь выбирает файл, приложение готовит изображение к отправке целиком — декодирует полноразмерный кадр в память, сжимает и держит результат до подтверждения сервера. Пока идёт загрузка изображений, лента ждёт ответа: оптимистичный пост висит в состоянии «отправляется», а интерфейс блокирует повторное нажатие, чтобы не ушло два дубля. На медленном канале ожидание растягивается на минуты.
Сбой отправки наступает предсказуемо: связь рвётся на последней трети тела запроса — и всё переданное теряется. Черновика нет: подготовленный кадр жил в оперативной памяти и вместе с ней исчез, а очередь повторов реагирует на сетевые ошибки, но не на закрытое приложение или уход в фон. Сжатие перед отправкой идёт в том же потоке: интерфейс не отзывчив, а прерывание процесса убивает и подготовку, и сам пост.
Повторяется это на каждом релизе, потому что логика размазана по экранам: экран создания поста хранит состояние у себя, отправка привязана к его жизненному циклу, а слой данных не знает о незавершённой публикации постов. Любой рефакторинг экрана — потеря черновика; обновление библиотеки выбора медиа — новый сбой на устройствах, где памяти под полноразмерный кадр не хватает и система снимает процесс.
Разбираем, как это закрывается: подготовка изображения порциями, локальная очередь с идемпотентным ключом и возобновляемая догрузка после обрыва — так пост переживает и потерю сети, и перезапуск приложения.
Что даёт управляемая загрузка медиа в приложении
Управляемая загрузка медиа — это отдельный слой между интерфейсом и хранилищем: очередь загрузок, локальный кэш и правила повторных попыток. Он разводит момент отправки поста и момент, когда файл реально лёг в хранилище, и именно от него зависит, ощущает ли пользователь приложение быстрым.
Отклик интерфейса при отправке
Пост появляется в ленте сразу — из локальной копии, а изображение уходит в фоне. Отклик интерфейса не зависит от скорости сети и размера снимка: экран не блокируется, прогресс виден на миниатюре, можно свернуть приложение или уйти на другой экран. Очередь загрузок продолжит работу и синхронизирует состояние, когда соединение вернётся.
Устойчивость очереди при слабой связи
Файл передаётся частями с контрольными суммами: оборванная сессия возобновляется с последней подтверждённой части, а не с нуля. Повторные попытки идут с нарастающей задержкой и потолком по числу — приложение не забивает канал и не расходует батарею в метро. Объём медиа сокращается ещё до отправки: пережатие в WebP и снятие служебных метаданных уменьшают вес снимка в 2-4 раза без видимой потери качества, поэтому тот же канал отдаёт заметно больше постов.
Доля неудачных загрузок на нестабильных сетях падает до единиц процентов, а серверная часть перестаёт принимать одни и те же файлы повторно — объём архива медиа растёт пропорционально числу постов, а не числу попыток.
Публикация постов: варианты сжатия и доставки изображений
Компромисс здесь всегда один и тот же: где резать качество, кто платит за это временем и какую нагрузку получают серверы. Ниже — четыре схемы, между которыми реально выбирают при публикации постов.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Сжатие на устройстве | Высокая частота постов, слабые каналы | Качество зависит от устройства, нужен запас по размеру |
| Оригинал на сервер, обработка там | Гарантированное качество картинки | Долгая публикация, пиковая нагрузка на серверы |
| Гибрид: превью с клиента, оригинал фоном | Основной сценарий ленты | Две фазы, нужна досылка и синхронизация |
| Отложенная обработка очередью | Пачки изображений, массовые загрузки | Задержка появления готового варианта |
Сжатие на устройстве
Клиент приводит кадр к разумному размеру по длинной стороне, переводит в современный формат с потерями и снимает метаданные — файл становится в разы меньше при визуально том же изображении. Это экономит трафик пользователя и разгружает приёмную часть, но качество перестаёт быть предсказуемым: разные устройства считают по-своему, а слабый телефон отдаёт заметно более мягкую картинку.
Серверная обработка и превью
Сервер принимает оригинал, режет его на наборы размеров под превью в ленте, полноэкранный просмотр и карточку, и раскладывает по сети доставки. Лента грузит лёгкое превью, полный кадр подтягивается по требованию — переключение между экранами остаётся мгновенным, а качество изображения одинаково для всех. Обратная сторона — очередь обработки, которую нужно держать под контролем и уметь переигрывать при сбое.
Этапы работ: аудит, схема, настройка, передача
Начинаем с разбора того, как медиа попадает в приложение сейчас: где готовится изображение, в каком виде уходит на сервер, что происходит при обрыве связи. Это точка отсчёта — без неё любая оптимизация превращается в догадки.
Аудит текущей схемы загрузки
- Собираем текущий путь публикации: подготовка файла, передача, ответ сервера, появление превью в ленте.
- Замеряем узкие места — вес отправляемого файла, время до показа превью, долю неудачных отправок на слабой сети.
- Фиксируем ограничения: права доступа, объёмы хранилища, требования модерации к контенту.
Согласование схемы и проверка на устройствах
- Проектируем схему хранения: где выполняется сжатие, какие варианты изображения отдаются под разные экраны, что остаётся в локальном кеше.
- Настраиваем сжатие: качество и формат подбираем под тип контента, ориентацию и метаданные выравниваем автоматически, вес держим разумным без видимой потери качества.
- Реализуем очередь отправки: повторные попытки при обрыве, догрузка в фоне, понятный статус публикации в интерфейсе.
- Проверяем на устройствах — слабая сеть, свёрнутое приложение, поворот экрана, нехватка памяти.
На выходе — рабочий путь публикации, документация по схеме и настройкам сжатия, обученная команда и чек-лист проверки для новых релизов.
Схемы, политики хранения и регламенты на выходе
После релиза у команды заказчика остаются не только исходники, но и схемы, конфигурации и регламенты, по которым приложение живёт и развивается без нас. Мы складываем их рядом с кодом, чтобы параметры сжатия менялись через ревью, а не вручную на сервере, а дежурный инженер понимал поток медиа по одной странице.
Схемы и конфигурации
- Схема потока медиа: от выбора файла в интерфейсе до появления поста — с точками сжатия, формирования превью и повторной отправки без дублирования публикации.
- Профили сжатия под сценарии: лента, полноэкранный просмотр, аватар — с целевым качеством и предельным размером файла для каждого.
- Конфигурация очереди загрузки: число одновременных задач, время ожидания ответа, правила повторов и поведение при обрыве связи.
- Политика хранения медиа: сроки жизни оригинала и превью, очистка файлов без привязки к посту, порядок удаления по запросу пользователя.
- Схема доступа: роли и сервисы с правом чтения и удаления объектов, порядок выдачи временных ссылок.
Инструкции для команды поддержки
- Регламент поддержки: как читать журналы неудачных публикаций и отличать сбой сжатия на устройстве от ошибки хранилища.
- Перечень типовых обращений с готовыми шагами разбора: изображение не загрузилось, превью расходится с постом, публикация ушла дважды.
- Порядок правки параметров сжатия: где менять, как проверить на тестовом наборе изображений и как вернуть предыдущие значения.
Кейс: сократили долю неудачных загрузок втрое
Клиент — мобильное приложение сервиса объявлений: пользователь публикует пост с 4–8 фотографиями прямо с телефона, в движении и на нестабильной сети. Исходный сценарий грузил кадры в полном разрешении одним запросом, а сервер уменьшал их синхронно — при обрыве связи отправка начиналась с нуля. Метрику считали по событиям в Sentry: каждая попытка логируется с кодом результата и этапом, на котором оборвалась.
Что было до
Доля неудачных загрузок держалась на уровне 21%: каждый пятый пост с фото пользователь отправлял повторно, а часть бросала на середине. Время отклика ленты после публикации доходило до 6 секунд — экран ждал, пока сервер приготовит производные размеры. Архив медиа рос без ограничений: повторные попытки плодили дубликаты исходников, и хранилище удваивалось примерно за год.
Что стало после
После внедрения сжатие переехало на устройство: кадр уменьшается по длинной стороне ещё до отправки, а превью появляется в ленте сразу — интерфейс не ждёт ответа сервера. Загрузка разбита на части и продолжается с точки обрыва, поэтому доля неудачных загрузок упала до 7% — втрое. Время отклика ленты сократилось до 1–2 секунд, а политика архива медиа оставляет исходник на 30 дней и хранит только производные — объём хранилища перестал расти при том же трафике.
Чем отличается клиентское сжатие от серверного?
Клиентское сжатие — уменьшение длинной стороны и перекодирование изображения до отправки: устройство отдаёт в сеть уже подготовленный файл без метаданных и лишних пикселей. Расход связи падает в разы, пост уходит даже на слабом канале, а серверная часть принимает предсказуемый по размеру поток. Плата — результат зависит от устройства: на слабом телефоне перекодирование затягивается и даёт артефакты.
Серверное сжатие — приём оригинала и подготовка всех производных на стороне сервиса: миниатюр, вариантов под разные плотности экрана, перекодирование в актуальные форматы. Правила обработки меняются без выпуска новой версии приложения, а качество выходит одинаковым на всех устройствах. Ограничение — исходник доезжает до сервера целиком, и нагрузка на сервер растёт на приёме, декодировании и хранении оригиналов.
Выбор — компромисс между расходом связи, качеством картинки и обработкой на бэкенде:
| Подход | Когда выбирать | Ограничения |
|---|---|---|
| Клиентское сжатие | Слабый канал, мобильный трафик, крупные фото с камеры | Качество и скорость зависят от устройства, оригинал теряется |
| Серверное сжатие | Нужны единые правила обработки и стабильное качество | Выше расход связи у пользователя, растёт нагрузка на приём и хранение |
| Гибридная схема | Нужны и быстрый показ, и сохранение оригинала | Сложнее логика: два прохода и согласование версий изображения |
При слабой связи выигрывает клиентское сжатие с ограничением по длинной стороне и фоновой догрузкой оригинала — пользователь быстрее видит свой пост. На стабильном канале предпочитают серверное: единые правила обработки проще поддерживать, а качество не зависит от парка устройств.
Частые технические сомнения и ограничения
Публикация поста с изображением — это не один запрос, а цепочка: выбор файла, сжатие, постановка в очередь, отправка, отрисовка. Сбои на каждом шаге воспроизводимы, а значит закрываются заранее — до того, как пользователь напишет «не загрузилось».
Ниже — ответы на то, что чаще всего всплывает при разборе такой схемы.
Что будет, если пользователь отправит пост дважды?
Каждой отправке присваивается идентификатор операции, а сервер хранит её результат. Повторный запрос с тем же ключом не создаёт второй пост, а возвращает уже созданный — это закрывает и двойной тап по кнопке, и повтор после обрыва.
Как ведёт себя загрузка при слабой связи?
Файл режется на части и загружается с докачкой: после обрыва отправка продолжается с последней подтверждённой части, а не с нуля. Сжатие происходит на устройстве до отправки, поэтому в сеть уходит в разы меньше данных.
Куда деваются исходники и превью?
Оригинал и уменьшенные копии хранятся раздельно, превью отдаётся из кеша на границе сети. Политика хранения по расписанию убирает неиспользуемые версии, а удаление поста чистит и оригинал, и производные.
Есть ли ограничения на стороне устройств?
Да: разные форматы съёмки, разный объём доступной памяти и агрессивное завершение фоновых процессов на iOS и Android. Поэтому сжатие идёт потоково, а очередь отправки восстанавливается после перезапуска приложения.
Обсудим вашу задачу и вернёмся с планом
Чтобы вернуться с оценкой задачи и планом работ, а не с общими обещаниями, нам нужно понять, как публикация постов устроена в вашем продукте: откуда приходит изображение, какое качество считается достаточным, что происходит при обрыве связи. Со своей стороны уточняем, что уже реализовано, а что предстоит собрать, и где в текущей архитектуре узкие места.
Дальше — что понадобится от вас и что мы проверяем сами. Расхождение именно в этих пунктах обычно и превращает задачу из «доделать экран» в «переписать половину загрузки».
- Что уже есть: текущий код приложения, доступы к репозиторию, макеты экрана создания поста — без этого оценка превращается в предположения.
- Сценарии публикации: откуда берётся изображение (галерея, камера, шаринг из другого приложения), сколько постов уходит одновременно, нужна ли очередь загрузки.
- Требования к результату: целевой вес файла, поведение при слабой сети, форматы на выходе, что видит пользователь, пока загрузка идёт.
- Что уточняем сами: сжатие на устройстве, догрузка после потери сети, отклик интерфейса на медленном канале.
- В каком виде вернёмся: оценка задачи по этапам, план работ с точками сдачи и перечень рисков.
- Дальше по циклу: поддержка приложения после запуска и передача документации — схемы, регламенты сборки и релиза, инструкции для вашей команды.
Опишите задачу в свободной форме — вернёмся с оценкой и планом работ.







