Как организовать надежный обмен документами с присоединенными тяжелыми файлами (фото/видео) в 1С при слабом канале связи?

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При организации распределенных информационных баз (РИБ) или обмена данными между центральным офисом и удаленными филиалами разработчики часто сталкиваются с проблемой "тяжелых" пакетов обмена. Если в периферийных узлах (например, на отдаленных складах или мобильных точках) пользователи активно прикрепляют к документам медиафайлы — фотографии отчетов, сканы документов, видеозаписи приемки товара — стандартный механизм обмена 1С начинает давать сбои. Причина кроется в том, что по умолчанию платформа сериализует бинарные данные в формат Base64 и помещает их внутрь единого монолитного XML-файла. На медленных и нестабильных каналах связи (GPRS, 3G/4G-модемы с низким уровнем сигнала) передача такого файла размером в десятки и сотни мегабайт становится практически невозможной: постоянные обрывы сессии приводят к повреждению архивов и бесконечным повторным попыткам выгрузки.

В рамках этой статьи мы детально проанализируем архитектурные подходы и технические решения, позволяющие обойти ограничения платформы, разгрузить транспортные каналы и гарантировать доставку документов и присоединенных файлов в центральную базу даже в самых неблагоприятных условиях связи.

Выясняем причины проблемы: почему падает стандартный обмен?

Давайте разберем, как устроен типовой обмен данными на базе планов обмена или БСП (Библиотеки стандартных подсистем). При регистрации изменений объектов система формирует единое сообщение обмена. Если в документе содержится реквизит с типом ХранилищеЗначения, хранящий тяжелую картинку, при выгрузке этот бинарный поток преобразуется в текстовую строку Base64. В результате:

  1. Размер XML-файла обмена увеличивается примерно на 33% по сравнению с исходным бинарным объемом файлов.
  2. При чтении и записи такого пакета СУБД и оперативная память сервера испытывают колоссальные нагрузки.
  3. Любой сетевой сбой в процессе передачи файла по каналам FTP или HTTP сводит к нулю весь прогресс — файл приходится передавать заново.
  4. При повреждении архива принимающая сторона не может прочитать даже легкие текстовые реквизиты документов, обмен полностью блокируется.

Ниже мы подробно рассмотрим несколько эффективных стратегий решения этой проблемы, которые позволяют оптимизировать производительность и повысить стабильность синхронизации.

Стратегия 1. Асинхронное разделение каналов: «Быстрые метаданные» и «Медленные файлы»

Это наиболее надежный архитектурный паттерн. Его суть заключается в том, чтобы полностью исключить бинарные данные из основного контура обмена. Через стандартный план обмена передаются только легкие XML-данные (реквизиты документов, табличные части и метаданные присоединенных файлов), а сами файлы отправляются параллельно по отдельному, более приспособленному каналу.

Разберем по шагам, как реализовать этот механизм:

  1. Исключение файлов из регистрации: В планах обмена снимаем регистрацию изменений для справочников или регистров, хранящих непосредственно двоичные данные присоединенных файлов (например, справочник Файлы или регистр сведений ДвоичныеДанныеФайлов).
  2. Передача метаданных: При создании документа в периферийной базе генерируется уникальный идентификатор файла (GUID). Этот GUID записывается в карточку присоединенного файла. Документ и элемент справочника-владельца файла регистрируются и улетают в центральную базу за доли секунды, так как весят несколько килобайт.
  3. Параллельная выгрузка файлов: Настраивается регламентное задание, которое выбирает новые файлы на диске или в базе данных, упаковывает их по одному и отправляет во внешнее облачное хранилище (например, S3, Яндекс.Диск) или на выделенный HTTP-сервер. Имя файла на сервере должно соответствовать его GUID.
  4. Связывание в центральной базе: При открытии формы документа в центральной базе система проверяет наличие файла в локальном кэше или томе хранения. Если файла нет, 1С отправляет асинхронный HTTP-запрос к внешнему хранилищу по GUID файла. Если файл найден — он скачивается и отображается пользователю. Если файл еще не успел загрузиться из периферийного узла, выводится заглушка «Файл загружается...», но работа пользователя с документом не блокируется.

Стратегия 2. Программный ресайз и сжатие картинок на стороне периферийной базы

Очень часто пользователи фотографируют документы на смартфоны с высоким разрешением камеры, в результате чего одна фотография весит от 5 до 15 МБ. Для большинства бизнес-задач (например, подтверждение факта отгрузки товара) такая детализация избыточна. Ограничение разрешения изображения до 1024x768 пикселей и сжатие качества JPEG до 70% уменьшает объем файла в 10–20 раз практически без потери читаемости текста.

Посмотрим на пример кода, реализующего программное сжатие изображения встроенными средствами платформы 1С:


Функция СжатьИзображение(ИсходныйДвоичныйОбъект, МаксимальнаяШирина = 1024, КачествоСжатия = 70) Экспорт
    
    Попытка
        КартинкаОбъект = Новый Картинка(ИсходныйДвоичныйОбъект);
        
        // Проверяем, требуется ли масштабирование
        Ширина = КартинкаОбъект.Ширина();
        Высота = КартинкаОбъект.Высота();
        
        Если Ширина > МаксимальнаяШирина Тогда
            Коэффициент = МаксимальнаяШирина / Ширина;
            НоваяШирина = МаксимальнаяШирина;
            НоваяВысота = Цел(Высота * Коэффициент);
            
            // Выполняем масштабирование картинки
            КартинкаОбъект = КартинкаОбъект.Преобразовать(ФорматКартинки.JPEG, НоваяШирина, НоваяВысота);
        Иначе
            // Если ресайз не нужен, просто преобразуем для изменения качества
            КартинкаОбъект = КартинкаОбъект.Преобразовать(ФорматКартинки.JPEG);
        КонецЕсли;
        
        // Получаем сжатые двоичные данные
        Возврат КартинкаОбъект.ПолучитьДвоичныеДанные();
        
    Исключение
        ЗаписатьЛогОшибок("Ошибка сжатия картинки: " + ОписаниеОшибки());
        Возврат ИсходныйДвоичныйОбъект;
    КонецПопытки;
    
КонецФункции

Этот код целесообразно вызывать в обработчике перед записью файла в периферийной базе. Сжатие должно происходить асинхронно или в фоновом задании, чтобы не заставлять пользователя ждать завершения процесса обработки в интерфейсе.

Стратегия 3. Потранзакционная выгрузка данных (Схема «1 документ = 1 пакет»)

Если бизнес-логика требует жесткого контроля доставки каждого документа вместе с его файлами в рамках одной транзакции, стандартный механизм выгрузки всего плана обмена в один файл не подходит. Мы можем самостоятельно написать обработку выгрузки, которая будет дробить изменения на отдельные пакеты.

Проанализируем пример кода, выполняющего выгрузку документов по одному файлу на каждый документ:


Процедура ВыгрузитьИзмененияПодокументно(УзелОбмена) Экспорт
    
    // Получаем зарегистрированные изменения для конкретного узла
    ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НомерСообщения);
    
    Пока ВыборкаИзменений.Следующий() Цикл
        
        ОбъектИзменения = ВыборкаИзменений.Получить();
        
        // Нас интересуют только документы конкретного типа со специфическим статусом
        Если ТипЗнч(ОбъектИзменения) = Тип("ДокументОбъект.УправлениеОтгрузкой") Тогда
            
            Если ОбъектИзменения.Статус = Перечисления.СтатусыОтгрузки.ГотовКОтправке Тогда
                
                // Начинаем формирование индивидуального XML-пакета
                ИмяФайлаПакета = ПолучитьИмяФайлаПакета(ОбъектИзменения.Ссылка);
                ЗаписьXML = Новый ЗаписьXML;
                ЗаписьXML.ОткрытьФайл(ИмяФайлаПакета);
                
                ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
                ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);
                
                // Выгружаем конкретный объект в XML
                ЗаписатьXML(ЗаписьXML, ОбъектИзменения);
                
                // Если у документа есть файлы, упаковываем их в ZIP вместе с XML
                АрхивироватьПакетСКартинками(ИмяФайлаПакета, ОбъектИзменения.Ссылка);
                
                ЗаписьСообщения.ЗакончитьЗапись();
                ЗаписьXML.Закрыть();
                
                // Отправляем сформированный архив на FTP/HTTP-сервер
                Если ОтправитьПакетНаТранспорт(ИмяФайлаПакета) Тогда
                    // Снимаем регистрацию изменений только для этого конкретного объекта
                    ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, ОбъектИзменения.Ссылка);
                КонецЕсли;
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Использование схемы «1 документ = 1 пакет» гарантирует, что даже на самом плохом канале связи документ небольшого размера (вместе со сжатыми фото) успешно загрузится за один короткий сеанс связи. Если сессия прервется, система повторит отправку только этого конкретного документа, а не всей базы за прошедший месяц.

Стратегия 4. Использование HTTP-сервисов с контролем целостности

Использование FTP-протокола на нестабильных мобильных сетях часто приводит к появлению "битых" файлов нулевого размера. HTTP-сервисы предоставляют гораздо более гибкие возможности по контролю целостности передаваемых пакетов.

При передаче файлов через специально разработанный HTTP-сервис в центральной базе мы можем реализовать следующий алгоритм контроля:

  1. Периферийная база перед отправкой вычисляет хеш-сумму MD5 файла.
  2. Файл отправляется по HTTP POST-запросу. В заголовках запроса передаются GUID документа, имя файла и MD5-хеш.
  3. Центральная база принимает файл, сохраняет его во временную папку и вычисляет MD5-хеш принятого файла.
  4. Если хеш-суммы совпадают, файл прикрепляется к документу в транзакции, и сервер возвращает статус 200 OK.
  5. Если контрольная сумма не совпала или произошел обрыв связи, центральная база удаляет поврежденный временный файл, а периферийная база получает команду на повторную отправку при следующем сеансе.

Для совсем критических условий связи можно реализовать блочную (чанковую) загрузку файлов, когда файл перед отправкой разбивается на части по 256–512 килобайт, и каждая часть отправляется независимо. После получения всех блоков центральная база собирает их обратно в один файл. Это полностью исключает проблему потери прогресса загрузки при обрывах связи.

Резюме и рекомендации

Для создания отказоустойчивой системы обмена данными в условиях нестабильного мобильного соединения рекомендуем придерживаться комплексного подхода:

← На главную