При разработке мобильных решений на платформе 1С часто возникает необходимость передать пакет данных с мобильного устройства в центральную информационную базу. Начинающие разработчики иногда сшивают данные в одну длинную строку с разделителями и отправляют бинарные файлы (фотографии, сканы) отдельными циклами через вызов веб-сервиса. Такой подход снижает производительность, усложняет поддержку кода и приводит к сбоям при нестабильном интернет-соединении.
В этой статье мы подробно разберем, как правильно организовать передачу сложных структур данных и графических файлов одной порцией с использованием JSON, XDTO и встроенных функций кодирования платформы 1С.
Рассмотрим типичную ошибку при работе с двоичными данными на мобильном клиенте. Попытка перевести двоичные данные (картинку) в строку простым оператором Строка(ДвоичныеДанные) приводит к получению представления байтов в шестнадцатеричном виде (HEX-формат, начинающийся с FF D8 FF E0...).
Такой подход имеет существенные недостатки:
ЗаписатьJSON() вызовет исключение, если ему передать объект типа ДвоичныеДанные напрямую, без предварительного конвертирования в текстовый формат.Для правильной работы с бинарными файлами в 1С используется кодирование Base64, которое увеличивает объем данных всего на ~33% и корректно поддерживается всеми встроенными механизми платформы.
Разберем по шагам создание структуры документа с массивом товаров и массивом картинок для отправки на сервер в формате JSON.
Шаг 1. Подготовка данных и конвертация изображений
Для перевода объекта ДвоичныеДанные в строку формата Base64 воспользуемся глобальной функцией Base64Строка().
// Формируем структуру документа
СтруктураДокумента = Новый Структура;
СтруктураДокумента.Вставить("Номер", ДокументОбъект.Номер);
СтруктураДокумента.Вставить("Дата", ДокументОбъект.Дата);
// Заполняем массив товаров
МассивТоваров = Новый Массив;
Для Каждого СтрИз ТЧТовары Цикл
СтруктураТовара = Новый Структура;
СтруктураТовара.Вставить("КодНоменклатуры", СтрИз.Номенклатура.Код);
СтруктураТовара.Вставить("Количество", СтрИз.Количество);
МассивТоваров.Добавить(СтруктураТовара);
КонецЦикла;
СтруктураДокумента.Вставить("МассивТоваров", МассивТоваров);
// Заполняем массив фото с кодированием в Base64
МассивКартинок = Новый Массив;
СписокКартинок = ДокументОбъект.Фотографии.Получить(); // Получаем массив или список двоичных данных
Для Каждого СтрФото Из СписокКартинок Цикл
// СтрФото.Значение содержит объект ДвоичныеДанные
СтрокаBase64 = Base64Строка(СтрФото.Значение);
МассивКартинок.Добавить(СтрокаBase64);
КонецЦикла;
СтруктураДокумента.Вставить("МассивКартинок", МассивКартинок);
Шаг 2. Сериализация структуры в JSON-строку
Скомпонованную структуру переводим в JSON-строку с помощью объектов ЗаписьJSON и ЗаписатьJSON:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураДокумента);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Передаем полученную строку в WS-функцию
Результат = Прокси.СохранитьДокументJSON(СтрокаJSON);
Шаг 3. Чтение и декодирование данных на стороне сервера
На сервере принимаем строку JSON, разбираем ее обратно в структуру и декодируем изображения с помощью функции Base64Значение():
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
ДанныеДокумента = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Обработка картинок
Для Каждого СтрокаBase64 Из ДанныеДокумента.МассивКартинок Цикл
ДвоичныеДанныеФото = Base64Значение(СтрокаBase64);
// Сохраняем фото в базу данных или на диск
// ...
КонецЦикла;
Многие разработчики ошибочно полагают, что если пакет XDTO создан в конфигурации сервера, его нельзя использовать в мобильном приложении без явного копирования структуры пакета в мобильную конфигурацию. Это не так.
При обращении к веб-сервису через объект WSПрокси платформа 1С автоматически считывает WSDL-описание сервиса с сервера и строит локальную фабрику XDTO прямо внутри прокси-объекта.
Разберем, как программно создавать объекты XDTO на мобильном клиенте:
// Подключаемся к веб-сервису
Определение = Новый WSОпределения(URL_WSDL, Логин, Пароль);
Прокси = Новый WSПрокси(Определение, URIПространстваИмен, ИмяСервиса, ИмяПорта);
// Получаем фабрику XDTO, созданную на основе WSDL-описания сервера
Фабрика = Прокси.ФабрикаXDTO;
// Получаем тип XDTO объекта с сервера
ТипДокумента = Фабрика.Тип("http://www.your-company.ru/exchange", "DocumentData");
ОбъектДокумент = Фабрика.Создать(ТипДокумента);
ОбъектДокумент.Number = ДокументОбъект.Номер;
ОбъектДокумент.Date = ДокументОбъект.Дата;
// Заполнение вложенных списков XDTO
ТипТовара = Фабрика.Тип("http://www.your-company.ru/exchange", "ItemData");
Для Каждого СтрИз ТЧТовары Цикл
ОбъектТовар = Фабрика.Создать(ТипТовара);
ОбъектТовар.Code = СтрИз.Номенклатура.Код;
ОбъектТовар.Quantity = СтрИз.Количество;
ОбъектДокумент.Items.Добавить(ОбъектТовар);
КонецЦикла;
// В свойства с типом xs:base64Binary можно передавать ДвоичныеДанные напрямую!
Для Каждого СтрФото Из СписокКартинок Цикл
ОбъектДокумент.Pictures.Добавить(СтрФото.Значение);
КонецЦикла;
// Отправляем сформированный объект XDTO на сервер одной операцией
Результат = Прокси.SaveDocument(ОбъектДокумент);
Важное примечание: Если в XDTO-пакете на сервере для свойства файла указан тип xs:base64Binary, то платформа 1С автоматически выполнит кодирование объекта ДвоичныеДанные в Base64 при отправке SOAP-запроса и декодирование при получении. Явно вызывать Base64Строка() в данном случае не требуется.
Проанализируем дополнительные способы оптимизации передачи графических данных с мобильных устройств:
КартинкаОригинал = Новый Картинка(ПутьКФайлу);
// Сжимаем изображение до приемлемого качества (например, 70%)
СжатыеДанные = КартинкаОригинал.ПолучитьДвоичныеДанныеСжатия(70);