Почему долго загружаются фото в мобильном приложении 1С и как это исправить?

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

Разработка мобильных приложений на платформе 1С:Предприятие имеет свою специфику, особенно когда дело касается работы с мультимедиа. Одной из частых проблем, с которой мы сталкиваемся, является крайне медленная отправка фотографий с мобильного устройства в центральную базу. Пользователи могут жаловаться на то, что приложение "виснет" на 40–50 секунд после снимка, даже при хорошем интернет-соединении и мощном сервере.

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

Анализ проблемы: почему фото грузится долго?

Рассмотрим ситуацию, описанную в исходной теме. У нас есть мобильное приложение (например, на базе УТ), которое делает фото. Связь с сервером отличная, сервер мощный, но момент "подгрузки" занимает неприемлемо много времени.

Если проанализировать типичные фотографии с современных смартфонов, мы увидим, что их объем составляет от 3 до 10 Мб (а иногда и больше). Однако сам по себе размер файла не является единственной причиной задержки. Главная проблема кроется в архитектуре передачи данных между клиентом (мобильным приложением) и сервером.

Давайте взглянем на фрагмент кода, который часто вызывает подобные "тормоза":


#Если МобильныйКлиент Тогда
    ДанныеМультимедиа = СредстваМультимедиа.СделатьФотоснимок();
    Если ДанныеМультимедиа <> Неопределено Тогда
        // ОШИБКА ЗДЕСЬ: Передача двоичных данных как параметра
        ВызовСделатьНовыйФайл(ДанныеМультимедиа.ПолучитьДвоичныеДанные(), 
                              ДанныеМультимедиа.РасширениеФайла, 
                              ДанныеМультимедиа.ТипСодержимого);
    КонецЕсли;
#КонецЕсли

&НаСервере
Процедура ВызовСделатьНовыйФайл(ДанныеМультимедиаДвоичныеДанные, ...)
    // Код создания файла
КонецПроцедуры

В чем здесь фундаментальная ошибка? Мы передаем ДвоичныеДанные (саму картинку) как параметр процедуры, вызываемой &НаСервере.

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

  1. Объем передаваемых данных увеличивается примерно на 30% из-за кодирования Base64.
  2. Самое важное: Процессор мобильного устройства тратит огромные ресурсы и время на сериализацию этого гигантского массива данных в строку перед отправкой. Именно в этот момент интерфейс "замирает".

Решение 1: Правильная архитектура передачи файлов

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

Алгоритм действий должен быть следующим:

  1. На клиенте помещаем файл во временное хранилище. Платформа делает это оптимизированно, потоком.
  2. Получаем строковый адрес (ссылку) на этот файл во временном хранилище.
  3. Передаем на сервер только этот короткий строковый адрес (UUID).
  4. На сервере по адресу извлекаем данные и сохраняем их.

Давайте перепишем код, используя правильный подход:


&НаКлиенте
Процедура СделатьФото(Команда)
    
    #Если МобильныйКлиент Тогда 
        // Настройки камеры (об этом ниже)
        РазрешениеКамеры = Новый РазрешениеКамерыУстройства(800, 600);
        КачествоКамеры = 80;
        
        ДанныеМультимедиа = СредстваМультимедиа.СделатьФотоснимок(, РазрешениеКамеры, КачествоКамеры,, ТипПодсветкиКамеры.Выключена);
            
        Если ДанныеМультимедиа <> Неопределено Тогда
            // ПРАВИЛЬНО: Помещаем во временное хранилище на клиенте
            АдресКартинки = ПоместитьВоВременноеХранилище(ДанныеМультимедиа.ПолучитьДвоичныеДанные(), УникальныйИдентификатор);
            
            // Вызываем серверную процедуру, передавая только адрес (строку)
            СохранитьФайлНаСервере(АдресКартинки, ДанныеМультимедиа.РасширениеФайла);
        КонецЕсли;
    #КонецЕсли

КонецПроцедуры

&НаСервере
Процедура СохранитьФайлНаСервере(АдресВременногоХранилища, Расширение)
    
    // Получаем данные из хранилища уже на стороне сервера
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
    
    // Далее логика сохранения файла в справочник или регистр
    // ...
    
КонецПроцедуры

Этот метод работает значительно быстрее, так как мы разгружаем механизм вызова серверных процедур от тяжелых данных.

Решение 2: Оптимизация исходного изображения

Даже при правильной архитектуре передача 10 Мб по мобильной сети может занять время. Для бизнес-задач (фото витрины, документы, поломки оборудования) редко требуется исходное разрешение 12-48 мегапикселей. Нам достаточно качественного, но легкого снимка.

Мы можем настроить параметры снимка непосредственно перед вызовом камеры, используя объекты РазрешениеКамерыУстройства и параметр качества.

Рассмотрим, как это реализуется в коде:


// Ограничиваем разрешение. 800x600 или 1024x768 обычно достаточно для большинства задач
РазрешениеКамеры = Новый РазрешениеКамерыУстройства(800, 600);

// Устанавливаем качество JPEG (от 0 до 100). 
// Значение 80 дает хорошее качество при значительно меньшем весе файла
КачествоКамеры = 80;

ДанныеМультимедиа = СредстваМультимедиа.СделатьФотоснимок(, РазрешениеКамеры, КачествоКамеры);

Такая предварительная настройка позволяет получить на выходе файл весом 200–500 Кб вместо 5–10 Мб, что ускоряет передачу в десятки раз.

Дополнительные возможности оптимизации

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

Обработка уже сделанных фото

Если пользователь выбирает фото из галереи, настройки РазрешениеКамерыУстройства не сработают, и мы снова получим огромный файл. В современных версиях мобильной платформы доступен объект ОбрабатываемаяКартинка. Он позволяет программно изменить размер (Resize) и сжать любое изображение перед отправкой.

Асинхронные вызовы

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

Пример схемы:

  1. Пользователь делает фото.
  2. Мы сохраняем его локально на устройстве.
  3. Фоновое задание или обработчик ожидания постепенно отправляет файлы на сервер, не мешая работе пользователя.

Использование HTTP-сервисов

Для максимальной скорости обмена данными часто отказываются от нативных механизмов 1С (планов обмена или вызовов серверных методов) в пользу HTTP-сервисов. Мобильное приложение формирует POST-запрос с телом картинки и отправляет его на опубликованный сервис базы УТ. Это самый быстрый способ, так как он исключает накладные расходы на синхронизацию сеансовых данных 1С.

Заключение

Проблема медленной загрузки фото решается комплексно. Главное правило: никогда не передавайте ДвоичныеДанные напрямую в параметрах серверных процедур. Используйте ПоместитьВоВременноеХранилище и обязательно ограничивайте разрешение и качество снимков средствами мультимедиа. Это обеспечит быструю и комфортную работу пользователей даже при нестабильном мобильном интернете.

← На главную